Модераторы: LSD, AntonSaburov
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Рисование в фрейме, В уже визуализированном 
:(
    Опции темы
Chupakabr
Дата 19.1.2010, 18:10 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 13
Регистрация: 3.12.2008

Репутация: нет
Всего: нет



Есть следующий кусок кода, который, как я понимаю, не работает от того, что рисование происходит в компоненте, и только затем он добавляется к фрейму. Проблема в том, что в методе paintComponent находится бесконечный цикл и соответственно после входа в него управление больше не передаётся фрейму(он зависает). Как рисовать в уже визуализированном фрейме?
Код

package graphics;

import java.awt.Graphics;
import java.util.Random;
import javax.swing.JComponent;
import javax.swing.JFrame;

public class ThirdFrame extends JFrame {
    
    public ThirdFrame() {
        setTitle(getClass().getSimpleName());
        setSize(400, 300);
        add(new MyComponent());
    }
    
    private class MyComponent extends JComponent {
        @Override
        public void paintComponent(Graphics g) {
            Random rm = new Random();
            for(;;) g.drawLine(rm.nextInt(400), rm.nextInt(300), rm.nextInt(400), rm.nextInt(300));
        }
    }
    
    public static void main(String... args) {
        ThirdFrame te = new ThirdFrame();
        te.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        te.setVisible(true);
    }

}




Это сообщение отредактировал(а) Chupakabr - 19.1.2010, 18:13
PM MAIL   Вверх
jk1
Дата 19.1.2010, 18:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Участник
Сообщений: 1168
Регистрация: 17.10.2008
Где: Санкт-Петербург

Репутация: 21
Всего: 75



Цитата

Как рисовать в уже визуализированном фрейме?

Вот пример рисования на видимом компоненте на основе вашего кода. Думаю, принцип понятен
Код

 public class ThirdFrame extends JFrame {

    ArrayList<Rectangle> rectangles = new ArrayList<Rectangle>();

    public ThirdFrame() {
        //setSize(400, 300);
        getContentPane().setLayout(new FlowLayout());
        MyComponent component = new MyComponent();
        component.setPreferredSize(new Dimension(300,400));
        add(component);
        JButton btn = new JButton("Добавить");
        btn.addActionListener(new ActionListener() {
            Random rm = new Random();
            @Override
            public void actionPerformed(ActionEvent e) {
              rectangles.add(new Rectangle(rm.nextInt(300),rm.nextInt(400),10,10));
              ThirdFrame.this.getContentPane().repaint();  
            }
        });
        add(btn);
        pack();
    }

    private class MyComponent extends JComponent {
        @Override
        public void paintComponent(Graphics g) {
            Random rm = new Random();
            for(Rectangle aRec:rectangles) {
                g.setColor(new Color(rm.nextInt(256),rm.nextInt(256),rm.nextInt(256)));
                g.fillRect(aRec.x,aRec.y,aRec.width,aRec.height);
            }
        }
    }

    public static void main(String... args) {
        ThirdFrame te = new ThirdFrame();
        te.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        te.setVisible(true);
    }
}



--------------------
Opinions are like assholes — everybody has one
PM MAIL   Вверх
Chupakabr
Дата 20.1.2010, 17:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 13
Регистрация: 3.12.2008

Репутация: нет
Всего: нет



Это вариант, но если, скажем, после нажатия кнопки, я хочу видеть как во фрейме/компоненте появляются новые квадратики или линии до тех пор, пока я не нажму кнопку "стоп". При таком раскладе добавление объектов (Rectangle/Line2D, которых может накопится несколько тысяч) в ArrayList и последующая перерисовка не есть делом благодарным.
Как по мне, сама концепция заполнения компонента с последующим добавлением во фрейм не позволяет осуществить бесконечный цикл. Может есть другие пути?
PM MAIL   Вверх
jk1
Дата 20.1.2010, 18:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Участник
Сообщений: 1168
Регистрация: 17.10.2008
Где: Санкт-Петербург

Репутация: 21
Всего: 75



Есть и другие варианты: создаете Image, рисуете в нем. Вот пример
Код

public class ThirdFrame extends JFrame {

    Image img;

    public ThirdFrame() {
        //setSize(400, 300);
        getContentPane().setLayout(new FlowLayout());
        MyComponent component = new MyComponent();
        component.setPreferredSize(new Dimension(300,400));
        add(component);
        JButton btn = new JButton("Добавить");
        btn.addActionListener(new ActionListener() {
            Random rm = new Random();

            @Override
            public void actionPerformed(ActionEvent e) {
                if(img==null){
                   img = createImage(300,400);

                }
                img.getGraphics().fillRect(rm.nextInt(300), rm.nextInt(400), 10, 10);
                 //label.setIcon(new ImageIcon(img));
                ThirdFrame.this.getContentPane().repaint(); 
            }
        });
        add(btn);
        setSize(600,400);
    }
     private class MyComponent extends JComponent {
        @Override
        public void paintComponent(Graphics g) {
            g.drawImage(img,0,0,null);
        }
    }

    public static void main(String... args) {
        ThirdFrame te = new ThirdFrame();
        te.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        te.setVisible(true);
    }
}

И никаких ArrayList'ов)


--------------------
Opinions are like assholes — everybody has one
PM MAIL   Вверх
Chupakabr
Дата 20.1.2010, 20:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 13
Регистрация: 3.12.2008

Репутация: нет
Всего: нет



Вроде как должно работать. Для интереса заключил строчки 21-23 вашего кода в while(true), но, при нажатии кнопки, фрейм всё равно виснет.

Это сообщение отредактировал(а) Chupakabr - 20.1.2010, 20:30
PM MAIL   Вверх
jk1
Дата 20.1.2010, 21:01 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Участник
Сообщений: 1168
Регистрация: 17.10.2008
Где: Санкт-Петербург

Репутация: 21
Всего: 75



Цитата

 фрейм всё равно виснет.

И будет виснуть, если использовать бесконечный цикл. Вы этим циклом останавливаете процесс отрисовки навсегда. В правильно построенном Swing-приложении отрисовка компонет и обработка событий выполняются в едином потоке, называемом EDT. Если вы хотите что-то выполнять параллельно (например генерировать новые графические примитивы и добавлять их на компонет) - нужно организовать отдельный поток. Удобно использовать для этой цели таймеры:
Код

public class ThirdFrame extends JFrame {

    Image img;
    Timer timer = new Timer(1000, new ActionListener() {
        Random rm = new Random();
        @Override
        public void actionPerformed(ActionEvent e) {
            if(img==null){
                   img = createImage(300,400);
                }
                Graphics g = img.getGraphics();
                g.setColor(new Color(rm.nextInt(256),rm.nextInt(256),rm.nextInt(256)));
                g.fillRect(rm.nextInt(300), rm.nextInt(400), 10, 10);

                ThirdFrame.this.getContentPane().repaint();
        }
    });
    public ThirdFrame() {
        //setSize(400, 300);
        getContentPane().setLayout(new FlowLayout());
        MyComponent component = new MyComponent();
        component.setPreferredSize(new Dimension(300,400));
        add(component);
        JButton btn = new JButton("Старт");
        btn.addActionListener(new ActionListener() {
          @Override
            public void actionPerformed(ActionEvent e) {
              timer.start();
            }
        });
        JButton stop = new JButton("Стоп");
        stop.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                timer.stop();
            }
        });
        add(btn);
        add(stop);
        setSize(600,400);
    }
     private class MyComponent extends JComponent {
        @Override
        public void paintComponent(Graphics g) {
            g.drawImage(img,0,0,null);
        }
    }



--------------------
Opinions are like assholes — everybody has one
PM MAIL   Вверх
Chupakabr
Дата 21.1.2010, 01:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 13
Регистрация: 3.12.2008

Репутация: нет
Всего: нет



Но если Timer работает в отдельном (рабочем, стало быть) потоке, то и прорисовка происходит там же: обработчик отвечающий за оную прицеплен именно к нему. Или я ошибаюсь?
PM MAIL   Вверх
jk1
Дата 21.1.2010, 07:47 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Участник
Сообщений: 1168
Регистрация: 17.10.2008
Где: Санкт-Петербург

Репутация: 21
Всего: 75



Ошибаетесь. Из javaDoc на таймер:
Цитата

Although all Timers perform their waiting
 using a single, shared thread 
 (created by the first Timer object that executes),
 the action event handlers for Timers
 execute on another thread -- the event-dispatching thread.
 This means that the action handlers for Timers
 can safely perform operations on Swing components.
 However, it also means that the handlers must execute quickly
  to keep the GUI responsive.



--------------------
Opinions are like assholes — everybody has one
PM MAIL   Вверх
Chupakabr
Дата 8.2.2010, 23:31 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 13
Регистрация: 3.12.2008

Репутация: нет
Всего: нет



С потоками вроде как разобрался и появились новые вопросы: в следующем коде при добавлении компонента Comp во фрейм, метод paintComponent почему-то вызывается дважды.

Код

package graphics;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.geom.Line2D;
import java.awt.geom.Rectangle2D;

import javax.swing.JComponent;
import javax.swing.JFrame;

public class Probka extends JFrame {
    
    public static void main(String [] args) {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                new Probka();
            }
        });
        
    }
    
    public Probka() {
        super("Probka");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        add(new Comp());
        //new Comp();
        pack();
        setVisible(true);
    }
    
    private class Comp extends JComponent {
        
        private Comp() {
            setPreferredSize(new Dimension(300, 200));
        }
        
        @Override
        protected void paintComponent(Graphics g) {
            /*Graphics2D g2 = (Graphics2D) g;
            Rectangle2D.Float rect = new Rectangle2D.Float(0f, 0f, 50f, 60f);
            Line2D.Float line = new Line2D.Float(1, 1, 10, 10);
            //Graphics2D g = (Graphics2D) getGraphics();
            g2.setColor(Color.CYAN);
            g2.draw(rect);
            g2.draw(line);
            g2.drawOval(5, 5, 20, 20);
            System.out.println(line.intersects(rect));*/
            System.out.println("Я вывожусь дважды.");
        }
    }

}




Это сообщение отредактировал(а) Chupakabr - 8.2.2010, 23:46
PM MAIL   Вверх
jk1
Дата 9.2.2010, 10:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Участник
Сообщений: 1168
Регистрация: 17.10.2008
Где: Санкт-Петербург

Репутация: 21
Всего: 75



Насколько мне известно, метод paintCmponent() будет вызван каждый раз, когда необходимо перерисовать окно. Происходить это может по разным причинам, поэтому общая рекомендация такая: пишите код отрисовки так, чтобы он не зависел от количества вызовов метода и в любой момент предоставлял адекватные данные для рисования.

И не забывайте вызывать super.paintComponent(g);.


--------------------
Opinions are like assholes — everybody has one
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Java"
LSD   AntonSaburov
powerOn   jk1
  • Прежде, чем задать вопрос, прочтите это!
  • Книги по Java собираются здесь.
  • Документация и ресурсы по Java находятся здесь.
  • Используйте теги [code=java][/code] для подсветки кода. Используйтe чекбокс "транслит", если у Вас нет русских шрифтов.
  • Помечайте свой вопрос как решённый, если на него получен ответ. Ссылка "Пометить как решённый" находится над первым постом.
  • Действия модераторов можно обсудить здесь.
  • FAQ раздела лежит здесь.

Если Вам помогли, и атмосфера форума Вам понравилась, то заходите к нам чаще! С уважением, LSD, AntonSaburov, powerOn, jk1.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Java: GUI и Java FX приложения | Следующая тема »


 




[ Время генерации скрипта: 0.0696 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.