Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / Java [игнор отключен] [закрыт для гостей] / Проблема с обновлением JPanel / 8 сообщений из 8, страница 1 из 1
25.02.2015, 13:38
    #38888398
Slavuti4
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Проблема с обновлением JPanel
Есть небольшая программа - по клику на JPanel на нее добавляются кнопки заданного размера и отображается количество уже добавленных кнопок.
Класс MainFrame - код основного окна, сделанный с помощью JFormDesigner

Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
123.
124.
125.
126.
127.
128.
129.
130.
131.
132.
133.
134.
135.
136.
137.
138.
139.
140.
141.
142.
143.
144.
145.
146.
147.
148.
import com.intellij.uiDesigner.core.GridConstraints;
import com.intellij.uiDesigner.core.GridLayoutManager;

import javax.swing.*;
import java.awt.*;


public class MainFrame {

	JFrame mainFrame;
	private JPanel topPanel;
	private JPanel paramPanel;
	private JLabel label1;
	JSpinner wSpinner;
	private JLabel label2;
	JSpinner hSpinner;
	JPanel resultPanel;
	JLabel resultLabel;
	JPanel centerPanel;
	int count = 0;


	public void initComponents() {
		// JFormDesigner - Component initialization - DO NOT MODIFY  //GEN-BEGIN:initComponents
		// Generated using JFormDesigner Evaluation license - sd sdsd
		mainFrame = new JFrame();
		topPanel = new JPanel();
		paramPanel = new JPanel();
		label1 = new JLabel();
		wSpinner = new JSpinner();
		label2 = new JLabel();
		hSpinner = new JSpinner();
		resultPanel = new JPanel();
		resultLabel = new JLabel();
		centerPanel = new JPanel();


		wSpinner.setValue( 50 );
		hSpinner.setValue( 50 );

		//======== mainFrame ========
		{
			mainFrame.setMinimumSize( new Dimension( 300, 300 ) );
			Container mainFrameContentPane = mainFrame.getContentPane();
			mainFrameContentPane.setLayout( new BorderLayout() );

			//======== topPanel ========
			{

				topPanel.setLayout( new GridLayoutManager( 2, 2, new Insets( 0, 0, 0, 0 ), 0, 0 ) );

				//======== paramPanel ========
				{
					paramPanel.setLayout( new GridLayoutManager( 2, 2, new Insets( 0, 0, 0, 0 ), -1, -1 ) );

					//---- label1 ----
					label1.setText( "Ширина" );
					paramPanel.add( label1, new GridConstraints( 0, 0, 1, 1, GridConstraints.ANCHOR_CENTER,
																 GridConstraints.FILL_NONE,
																 GridConstraints.SIZEPOLICY_CAN_SHRINK |
																 GridConstraints.SIZEPOLICY_CAN_GROW,
																 GridConstraints.SIZEPOLICY_CAN_SHRINK |
																 GridConstraints.SIZEPOLICY_CAN_GROW, null, null,
																 null ) );

					paramPanel.add( wSpinner, new GridConstraints( 0, 1, 1, 1, GridConstraints.ANCHOR_CENTER,
																   GridConstraints.FILL_NONE,
																   GridConstraints.SIZEPOLICY_CAN_SHRINK |
																   GridConstraints.SIZEPOLICY_CAN_GROW,
																   GridConstraints.SIZEPOLICY_CAN_SHRINK |
																   GridConstraints.SIZEPOLICY_CAN_GROW, null, null,
																   null ) );

					//---- label2 ----
					label2.setText( "Высота" );
					paramPanel.add( label2, new GridConstraints( 1, 0, 1, 1, GridConstraints.ANCHOR_CENTER,
																 GridConstraints.FILL_NONE,
																 GridConstraints.SIZEPOLICY_CAN_SHRINK |
																 GridConstraints.SIZEPOLICY_CAN_GROW,
																 GridConstraints.SIZEPOLICY_CAN_SHRINK |
																 GridConstraints.SIZEPOLICY_CAN_GROW, null, null,
																 null ) );
					paramPanel.add( hSpinner, new GridConstraints( 1, 1, 1, 1, GridConstraints.ANCHOR_CENTER,
																   GridConstraints.FILL_NONE,
																   GridConstraints.SIZEPOLICY_CAN_SHRINK |
																   GridConstraints.SIZEPOLICY_CAN_GROW,
																   GridConstraints.SIZEPOLICY_CAN_SHRINK |
																   GridConstraints.SIZEPOLICY_CAN_GROW, null, null,
																   null ) );
				}
				topPanel.add( paramPanel,
							  new GridConstraints( 0, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints
									  .FILL_NONE,
												   GridConstraints.SIZEPOLICY_CAN_SHRINK |
												   GridConstraints.SIZEPOLICY_CAN_GROW,
												   GridConstraints.SIZEPOLICY_CAN_SHRINK |
												   GridConstraints.SIZEPOLICY_CAN_GROW, null, null, null ) );

				//======== resultPanel ========
				{
					resultPanel.setLayout( new GridLayoutManager( 2, 2, new Insets( 0, 0, 0, 0 ), -1, -1 ) );

					//---- resultLabel ----
					resultLabel.setText( "text" );
					resultPanel.add( resultLabel, new GridConstraints( 0, 0, 1, 1, GridConstraints.ANCHOR_CENTER,
																	   GridConstraints.FILL_NONE,
																	   GridConstraints.SIZEPOLICY_CAN_SHRINK |
																	   GridConstraints.SIZEPOLICY_CAN_GROW,
																	   GridConstraints.SIZEPOLICY_CAN_SHRINK |
																	   GridConstraints.SIZEPOLICY_CAN_GROW, null, null,
																	   null ) );
				}
				topPanel.add( resultPanel,
							  new GridConstraints( 0, 1, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints
									  .FILL_NONE,
												   GridConstraints.SIZEPOLICY_CAN_SHRINK |
												   GridConstraints.SIZEPOLICY_CAN_GROW,
												   GridConstraints.SIZEPOLICY_CAN_SHRINK |
												   GridConstraints.SIZEPOLICY_CAN_GROW, null, null, null ) );
			}
			mainFrameContentPane.add( topPanel, BorderLayout.NORTH );

			//======== centerPanel ========
			{
				centerPanel.setBackground( Color.white );
				centerPanel.setMinimumSize( new Dimension( 300, 300 ) );
				centerPanel.addMouseListener( new MouseListener( this ) );
			}
			mainFrameContentPane.add( centerPanel, BorderLayout.CENTER );
			mainFrame.pack();
			mainFrame.setLocationRelativeTo( mainFrame.getOwner() );
			mainFrame.setVisible( true );
			mainFrame.setDefaultCloseOperation( WindowConstants.EXIT_ON_CLOSE );
		}
		// JFormDesigner - End of component initialization  //GEN-END:initComponents
	}

	void updateCount() {
		count++;
		//resultLabel.setText( String.valueOf( count ) );
		
	}

	public static void main( String[] args ) {
		new MainFrame().initComponents();
	}

}



И класс MouseListener:
Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
import javax.swing.*;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;

import static java.awt.event.MouseEvent.BUTTON1;
import static java.awt.event.MouseEvent.BUTTON3;

public class MouseListener extends MouseAdapter {

	private MainFrame frame;

	public MouseListener( MainFrame mainFrame ) {
		this.frame = mainFrame;
	}

	@Override
	public void mouseClicked( MouseEvent e ) {
		if( e.getButton() == BUTTON1 || e.getButton() == BUTTON3 ) {
			JButton button = new JButton();
			button.setBounds( getBounds( e, frame ) );

			frame.centerPanel.add( button );
			frame.updateCount();
			frame.mainFrame.repaint();

		}
	}

	Rectangle getBounds( MouseEvent e, MainFrame frame ) {
		int w = Integer.parseInt( frame.wSpinner.getValue().toString() );
		int h = Integer.parseInt( frame.hSpinner.getValue().toString() );
		int x = e.getX();
		int y = e.getY();
		System.out.println( "added " + x + " " + y + " " + h + " " + w );
		return new Rectangle( x, y, w, h );
	}
}



Проблема вот в чем - если в методе updateCount() изменить надпись на JLabel с помощью setText, происходит следующее:

Если же закомментировать этот момент, то все в порядке:

Тоже самое происходит, если изменить вручную размеры окна.
Изучив гугл, пришел к выводу, что это происходит из-за метода updateUI(), который, видимо, вызывается автоматически. Если его вызвать вручную - проблема повторяется.
Подскажите, в какую сторону вообще копать? Виноват компоновщик или еще что-то?
И сразу второй вопрос - при добавлении этих самых кнопок по клику заметил, что событие не всегда срабатывает - если кликать быстро, то вообще ничего не добавляется. Если убрать repaint() - задержка вообще почти всегда. С чем это связано?
Заранее спасибо за любое объяснение\статьи и прочее :)
...
Рейтинг: 0 / 0
25.02.2015, 13:54
    #38888431
Blazkowicz
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Проблема с обновлением JPanel
Код: java
1.
centerPanel.setLayout(null);

Это необходимо для ручного позиционирования. Так как по-умолчанию используется FlowLayout. Из-за этого все проблемы. Потому что Layout manager не использует те Bounds что вы устанавливаете. Он используется PreferredSize. А Bounds устанавливает сам.

Забудьте про repaint() и updateUI(). Это рудименты, в которые новички постоянно утыкаются при борьбе с layout manager.
updateUI() относится к LookAndFeel. Класс отвечающий за отрисовку контрола в LAF имеет суффикс UI. Вот updateUI обновляет этот объект отрисовки привязанный к контролу.
repaint() не помню что именно там делает, но тоже не предназначен для ручного вызова из кода.
...
Рейтинг: 0 / 0
25.02.2015, 19:12
    #38888862
Slavuti4
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Проблема с обновлением JPanel
Blazkowicz, огромное спасибо! А что по поводу лагов GUI? Это все Swing & потоки, в этом направлении разбираться?
...
Рейтинг: 0 / 0
25.02.2015, 20:26
    #38888901
Blazkowicz
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Проблема с обновлением JPanel
Slavuti4Blazkowicz, огромное спасибо! А что по поводу лагов GUI? Это все Swing & потоки, в этом направлении разбираться?
В чем конкретно лаги? Если updateUI и repaint убрать то и лагов не должно быть.
...
Рейтинг: 0 / 0
25.02.2015, 20:43
    #38888913
Slavuti4
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Проблема с обновлением JPanel
Blazkowicz, когда быстро щелкаешь ЛКМ/ПКМ - кнопка не добавляется, либо вместо 2-3 добавляется всего 1. Даже в консоли пишет, что кнопка добавилась (отработал слушатель), цифра через setText изменилась, а кнопки нет. Либо кнопка добавляется с заметным запаздыванием. При быстрых кликах вообще ничего не происходит
...
Рейтинг: 0 / 0
26.02.2015, 09:41
    #38889129
Blazkowicz
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Проблема с обновлением JPanel
Slavuti4Blazkowicz, когда быстро щелкаешь ЛКМ/ПКМ - кнопка не добавляется, либо вместо 2-3 добавляется всего 1. Даже в консоли пишет, что кнопка добавилась (отработал слушатель), цифра через setText изменилась, а кнопки нет. Либо кнопка добавляется с заметным запаздыванием. При быстрых кликах вообще ничего не происходит
Много быстрых нажатий система воспринимает как double и даже triple click. MouseEvent.getClickCount().

Хочу так же отметить, что Swing это фреймверк для создания GUI. Делать на него основе какую-то "игру" это использовать его не по назначению. Конечно, будет намного быстрее если выкинуть контролы и вместо них реализовать свою модель с прямым отображением в Java2D.

Ещё достаточно странно что для вашей задачи вы выбрали Swing, а не JavaFX.
...
Рейтинг: 0 / 0
26.02.2015, 12:43
    #38889348
mayton
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Проблема с обновлением JPanel
А есть у кого-то образец JavaFX проекта с гридами?
...
Рейтинг: 0 / 0
26.02.2015, 12:56
    #38889371
Slavuti4
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Проблема с обновлением JPanel
Blazkowicz, большое спасибо, проблема решилась заменой mouseClicked() на mousePressed(). Swing использую просто для того, чтобы детально разобраться, как все работает, потом переделаю на чем-нибудь более современном :)
...
Рейтинг: 0 / 0
Форумы / Java [игнор отключен] [закрыт для гостей] / Проблема с обновлением JPanel / 8 сообщений из 8, страница 1 из 1
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]