Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Java: GUI и Java FX приложения > Перерисовка JPanel и задержка Thread.sleep()


Автор: agR 16.3.2008, 18:02
При очередной попытке изобрести велосипед наткнулся на странное (пока) для меня поведение JPanel при попытке изменить ее рамку.
Не мог бы кто-то обяснить, как правильно написать код для изменения рамки панели? Пока я пытаюсь делать так:
Код

Action loginAction = new AbstractAction() {
            @Override
            public void actionPerformed(ActionEvent e) {
                if (verifyingData()) {          //verifyingData() всегда true (для примера)
                    changeBorder();
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e1) {
                        e1.printStackTrace();
                    }
                    dispose();      //здесь как бы окно для входа зыкрывается
                    frame = new OrganizerWindow();      //основное окно работы
                    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                    frame.setVisible(true);
                    
                }
            }

    public void changeBorder() {
        panel.setBorder(BorderFactory.createTitledBorder(BorderFactory.createLineBorder(Color.GREEN), "Autorization"));
        panel.repaint();
    }



В конструкторе панели цвет рамки указывался красным, а потом по определенному событию я хотел бы увидеть, чтоб она стала зеленой.
Подскажите плз как правильно.


Автор: agR 17.3.2008, 13:42
Вот привожу код, который можно "пощупать".... в нем много лишнего, но все таки так и не ясно, почему не сробатывает repaint()....
Код

import javax.swing.*;

import java.awt.*;
import java.awt.event.ActionEvent;

public class AutinificationWindow extends JFrame {
    public AutinificationWindow() {
        super("(aGr)anizer");
        panel = createAutorizationPanel();
        getContentPane().add(panel);
        pack();
        setResizable(false);
        setLocationRelativeTo(null);
    }
    
    
    public JPanel createAutorizationPanel() {
        JPanel panel = new JPanel();
        panel.setLayout(new BoxLayout(panel,BoxLayout.Y_AXIS));
        panel.setBorder(BorderFactory.createTitledBorder(BorderFactory.createLineBorder(Color.RED), "Autorization"));
        
        JPanel loginPanel = new JPanel();
        loginPanel.setLayout(new BoxLayout(loginPanel,BoxLayout.X_AXIS));
        
        JPanel passPanel = new JPanel();
        passPanel.setLayout(new BoxLayout(passPanel, BoxLayout.X_AXIS));
        
        JPanel buttonPanel = new JPanel();
        buttonPanel.setLayout(new BoxLayout(buttonPanel, BoxLayout.X_AXIS));
        
        JLabel loginLabel = new JLabel();
        JLabel passLabel = new JLabel();
        //---------------------------------
        loginLabel.setText("Login: ");
        passLabel.setText("Password: ");
        //----------------------------------
        GUITools.makeSameSize(new JComponent[]{loginLabel, passLabel});
        //---------------------------------
        loginField = new JTextField(15);
        passField = new JPasswordField(15);
        
        GUITools.makeSameSize(new JComponent[] {loginField, passField});
        //---------------------------------
        loginPanel.add(loginLabel);
        loginPanel.add(Box.createHorizontalStrut(5));
        loginPanel.add(loginField);
        
        passPanel.add(passLabel);
        passPanel.add(Box.createHorizontalStrut(5));
        passPanel.add(passField);
        
        //--------------------------------
        okButton = new JButton("Login");
        exitButton = new JButton("Exit");
        Action loginAction = new AbstractAction() {
            @Override
            public void actionPerformed(ActionEvent e) {
                if (verifyingData()) {
                    changeBorder();
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e1) {
                        // TODO Auto-generated catch block
                        e1.printStackTrace();
                    }
                    dispose();
                    frame = new OrganizerWindow();
                    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                    frame.setVisible(true);
                    
                }
            }
            
        };
        Action exitAction = new AbstractAction() {
            @Override
            public void actionPerformed(ActionEvent e) {
                System.exit(0);
            }
        };
        okButton.addActionListener(loginAction);
        //okButton.addActionListener(new LoginAction());
        exitButton.addActionListener(exitAction);
        
        buttonPanel.add(okButton);
        buttonPanel.add(Box.createHorizontalStrut(17));
        buttonPanel.add(exitButton);
        
        GUITools.makeSameSize(new JComponent[] {okButton,exitButton});
        //--------------------------------
        panel.add(Box.createVerticalStrut(7));
        panel.add(loginPanel);
        panel.add(Box.createVerticalStrut(7));
        panel.add(passPanel);
        panel.add(Box.createVerticalStrut(7));
        panel.add(buttonPanel);
        panel.add(Box.createVerticalStrut(7));
        
        return panel;
    }
    
    public void changeBorder() {
        panel.setBorder(BorderFactory.createTitledBorder(BorderFactory.createLineBorder(Color.GREEN), "Autorization"));
        panel.repaint();
    }
    public boolean verifyingData() {
        verifyed = false;
        
        
        verifyed = true;
        
        return verifyed;
    }
    
    public OrganizerWindow getOrganizeWindow() {
        return frame;
    }
    
    public JPanel getAutPanel() {
        return panel;
    }
    private class LoginAction extends AbstractAction {
        @Override
        public void actionPerformed(ActionEvent e) {
            panel.setBorder(BorderFactory.createTitledBorder(BorderFactory.createLineBorder(Color.GREEN), "Autorization"));
            panel.repaint();
            
        }
    }
    
    private JTextField loginField;
    private JPasswordField passField;
    private JButton okButton;
    private JButton exitButton;
    private boolean  verifyed;
    private OrganizerWindow frame;
    private JPanel panel;
}



Вот вспомагательный класс GUITools:

Код

import java.awt.Dimension;

import javax.swing.JComponent;

class GUITools {

    // инструмент для придания группе компонентов
    // одинаковых размеров (минимальных,
    // предпочтительных и максимальных).
    // Компоненты принимают размер самого
    // большого (по ширине) компонента в группе
    public static void makeSameSize(JComponent[] components) {
        // получение ширины компонентов
        int[] sizes = new int[components.length];
        for (int i=0; i<sizes.length; i++) {
            sizes[i] = components[i].getPreferredSize().width;      
        }
        // определение максимального размера
        int maxSizePos = maximumElementPosition(sizes);
        Dimension maxSize =
            components[maxSizePos].getPreferredSize();
        // придание одинаковых размеров
        for (int i=0; i<components.length; i++)    {
            components[i].setPreferredSize(maxSize);
            components[i].setMinimumSize(maxSize);
            components[i].setMaximumSize(maxSize);
        }
    }  

    // вспомогательный метод для определения позиции
    // максимального элемента массива
    private static int maximumElementPosition(int[] array) {
        int maxPos = 0;
        for (int i=1; i < array.length; i++) {
            if (array[i] > array [maxPos]) maxPos = i;
        }
        return maxPos;
    }
}


если в этом месте: 
Код

Action loginAction = new AbstractAction() {
            @Override
            public void actionPerformed(ActionEvent e) {
                if (verifyingData()) {
                    changeBorder();
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e1) {
                        // TODO Auto-generated catch block
                        e1.printStackTrace();
                    }
                    dispose();
                    frame = new OrganizerWindow();
                    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                    frame.setVisible(true);
                    
                }
            }
            
        };


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

Автор: agR 17.3.2008, 15:07
Все... вроде как решил, но на сколько это правильно - хз  smile 
Вместо Thread.sleep() теперь используется Timer:

Код

Action loginAction = new AbstractAction() {
            @Override
            public void actionPerformed(ActionEvent e) {
                if (verifyingData()) {
                    changeBorder();
                    t = new Timer(2000, new LoginAction());
                    t.start();
                    
                }
            }
            
        };


Код

private class LoginAction extends AbstractAction {
        @Override
        public void actionPerformed(ActionEvent e) {
            dispose();
            frame = new OrganizerWindow();
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.setVisible(true);
            t.stop();
        }
    }


Надеюсь, это верное решение  smile 

Автор: niasilil 17.3.2008, 19:08
я код не запускал, но пару слов сказать могу smile

Когда ты запускаешь sleep, ты заставляешь данный thread заснуть. То есть все перересовывания не будут поисходить пока thread не проснется. Когда ты запускаешь Timer, то он запускается в отдельном thread, соответственно основной у тебя имеет возможность продолжать работать - перересовывать все что хочешь. Rule of thumb: все задачи занимающие дольше чем 100 ms не стоит запускать в Event dispatch thread, а в отдельном thread. 

http://java.sun.com/products/jfc/tsc/articles/threads/threads1.html
http://java.sun.com/products/jfc/tsc/articles/threads/threads2.html
http://java.sun.com/products/jfc/tsc/articles/threads/threads3.html

Автор: agR 17.3.2008, 19:16
Цитата(niasilil @  17.3.2008,  19:08 Найти цитируемый пост)
Rule of thumb: все задачи занимающие дольше чем 100 ms не стоит запускать в Event dispatch thread, а в отдельном thread.

Спасибо, запомню  smile 

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)