#java #arrays #swing #jframe #jbutton
Вопрос:
После добавления объекта класса Puzzle в Main все отображается в основном так, как должно. когда я нажимаю на любую из кнопок, некоторые индексы состояния должны меняться на противоположные, так что от true к false или от false к true.
к сожалению, нажатие кнопки не хочет регистрироваться ни для одной кнопки из массива, но оно регистрируется для одной кнопки, которая была инициализирована сама по себе. Как я могу решить эту проблему?
мой код:
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Arrays;
public class Puzzle extends JFrame implements ActionListener
{
int doors = 8;
boolean [] state = new boolean[doors];
JButton [] levers = new JButton[doors];
JButton weird = new JButton("weird lever");
JLabel display = new JLabel();
Puzzle()
{
reset();
this.setSize(new Dimension(1920, 1080));
this.setVisible(true);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setLocationRelativeTo(null);
this.setVisible(true);
this.setResizable(false);
this.setLayout(null);
this.add(display);
this.add(weird);
int num = levers.length;
int start = 50;
int size = (1920-(num 1)*start)/num;
char label = 'A';
display.setBounds(size*2, 150, 2000, 300);
display.setFont(new Font("Arial Black", Font.PLAIN, 200));
Display();
for(JButton i : levers)
{
i = new JButton(String.valueOf(label));
label ;
i.setBounds(start, 500, size, size);
start =(size 50);
i.addActionListener(this);
i.setFont(new Font("Arial black", Font.PLAIN, size/2));
i.setFocusable(false);
this.add(i);
}
weird.setFocusable(false);
weird.setBounds(550, 800, 800, 200);
weird.setFont(new Font("Arial Black", Font.PLAIN, size/2));
weird.addActionListener(this);
}
@Override
public void actionPerformed(ActionEvent e)
{
/*if(e.getSource() == levers[0])
{
state[2] = Swap(state[2]);
Display();
}
if(e.getSource() == levers[1])
{
state[4] = Swap(state[4]);
state[6] = Swap(state[6]);
Display();
}
if(e.getSource() == levers[2])
{
state[2] = Swap(state[2]);
state[3] = Swap(state[3]);
state[6] = Swap(state[6]);
state[7] = Swap(state[7]);
Display();
}
if(e.getSource() == levers[3])
{
state[0] = Swap(state[0]);
state[2] = Swap(state[2]);
state[7] = Swap(state[7]);
Display();
}
if(e.getSource() == levers[4])
{
state[1] = Swap(state[1]);
state[3] = Swap(state[3]);
state[4] = Swap(state[4]);
state[5] = Swap(state[5]);
Display();
}
if(e.getSource() == levers[5])
{
state[0] = Swap(state[0]);
state[2] = Swap(state[2]);
state[6] = Swap(state[6]);
Display();
}
if(e.getSource() == levers[6])
{
state[1] = Swap(state[1]);
state[5] = Swap(state[5]);
Display();
}
if(e.getSource() == levers[7])
{
state[1] = Swap(state[1]);
state[2] = Swap(state[2]);
state[4] = Swap(state[4]);
state[5] = Swap(state[5]);
Display();
}
*/
if(e.getSource() == levers[0])
{
display.setText("A works");
}
if(e.getSource() == weird)
{
display.setText("test");
}
}
boolean Swap(boolean n)
{
return !n;
}
void Display()
{
StringBuilder toDisplay = new StringBuilder();
for (boolean j : state)
{
if (j)
{
toDisplay.append("| ");
} else
toDisplay.append("_ ");
}
display.setText(toDisplay.toString());
}
void reset ()
{
Arrays.fill(state, true);
}
}```
Ответ №1:
нажатие кнопки не хочет регистрироваться ни для одной кнопки из массива, но все же регистрируется для одной кнопки
System.out.println( levers[0] );
if(e.getSource() == levers[0])
{
display.setText("A works");
}
Добавьте некоторый отладочный код в свой список действий, и вы увидите, что значение levers[0]
равно «null».
for(JButton i : levers)
{
i = new JButton(String.valueOf(label));
label ;
i.setBounds(start, 500, size, size);
start =(size 50);
i.addActionListener(this);
i.setFont(new Font("Arial black", Font.PLAIN, size/2));
i.setFocusable(false);
this.add(i);
}
Вы создаете кнопку, но никогда не добавляете экземпляр каждой кнопки в массив.
for(JButton i : levers)
Почему вы используете «я» в качестве имени переменной? Обычно в качестве индекса используется «i». Используйте правильное имя переменной, например «кнопка». Однако в этом случае вы не хотите использовать цикл «для каждого».
Вместо этого вам нужен обычный цикл for, чтобы вы могли индексировать свой массив, добавляя каждую кнопку по мере ее создания:
//for(JButton i : levers)
for (int i = 0; i < doors; i )
{
JButton button = new JButton(String.valueOf(label));
levers[i] = button;
...
Другие вопросы:
- имена методов не должны начинаться с символа верхнего регистра.
- компоненты должны быть добавлены в рамку ДО того, как рамка станет видимой.
- компоненты должны быть созданы на
Event Dispatch Thread (EDT)
. - Не используйте нулевую компоновку и setBounds(). Swing был разработан для использования с менеджерами по компоновке.
- Не устанавливайте размеры экрана жестко. Вместо этого вы можете использовать
frame.setExtendedState(JFrame.MAXIMIZED_BOTH);
, поэтому он будет работать для всех размеров экрана.
Комментарии:
1. Спасибо, я бы сделал обычный цикл for, но Intellij предложил вместо этого использовать для каждого.
Ответ №2:
Введение
Ваш код был слишком сложным, чтобы я мог его понять. Мне нравится простой код. Короткие методы и простые классы.
Вот графический интерфейс, который я придумал.
Вот графический интерфейс после того, как я нажал пару букв JButtons
Объяснение
У Oracle есть отличный учебник по созданию графического интерфейса с помощью JFC/Swing, который покажет вам, как создать графический интерфейс Swing. Пропустите раздел Netbeans.
В вашем коде отсутствовал основной метод, поэтому я добавил один. Я запустил приложение Swing с помощью вызова SwingUtilities
invokeLater
метода. Этот метод гарантирует, что компоненты Swing создаются и выполняются в потоке отправки событий.
Первое, что я сделал, это создал PuzzleModel
класс для хранения логического массива. Это хорошая идея, чтобы отделить вашу модель от вашего представления и классов контроллеров. Этот шаблон является шаблоном модели / представления / контроллера (MVC).
Качели JFrame
могут содержать много JPanels
. Я создал сегмент JPanel
для размещения a JLabel
и a JButton
, выровненных по вертикали. Я использовал GridBagLayout
его для выравнивания JLabel
и. JButton
Менеджеры по компоновке Swing помогут вам избежать абсолютного позиционирования и проблем, связанных с абсолютным позиционированием.
Я создал основную JPanel
для размещения 8 сегментов JPanels
. Они JPanels
выровнены с a FlowLayout
.
Как вы можете видеть, мой JFrame
размер меньше вашего. Вы создаете JFrame
как можно меньшее число «а». Если пользователь хочет сделать его больше, для этого и предназначен прямоугольник в правом верхнем углу.
Качели предназначены для того, чтобы быть спроектированными изнутри наружу. Вы не указываете JFrame
размер и не пытаетесь подгонять компоненты. Вы создаете компоненты и позволяете Swing определять размер JFrame
. Если вы хотите JFrame
, чтобы созданный мной шрифт был больше, увеличьте размеры шрифта. Подсказка: Доля или кратность 72 баллов выглядит лучше на большинстве дисплеев.
Я создал два ActionListener
класса, один для алфавита JButtons
, а другой для рычага JButton
. Это облегчает фокусировку на алфавите JButtons
. Все, что вам нужно сделать ActionListener
, — это поменять местами соответствующие isVertical
логические значения при щелчке левой кнопкой мыши на каждой кнопке. Я просто перевернул соответствующее логическое значение в качестве демонстрации.
Код
Вот полный исполняемый код.
import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Arrays;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class PuzzleGUI implements Runnable {
public static void main(String[] args) {
SwingUtilities.invokeLater(new PuzzleGUI());
}
private JLabel[] leverLabel;
private final PuzzleModel model;
public PuzzleGUI() {
this.model = new PuzzleModel();
}
@Override
public void run() {
JFrame frame = new JFrame("Weird Lever");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(createMainPanel(), BorderLayout.CENTER);
frame.add(createButtonPanel(), BorderLayout.AFTER_LAST_LINE);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
System.out.println(frame.getSize());
}
private JPanel createMainPanel() {
JPanel panel = new JPanel(new FlowLayout());
panel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
char c = 'A';
boolean[] isVertical = model.getIsVertical();
leverLabel = new JLabel[isVertical.length];
for (int i = 0; i < isVertical.length; i ) {
String labelText = (isVertical[i]) ? "|" : "-";
panel.add(createLeverButtonPanel(labelText, Character.toString(c), i));
c = (char) (((int) c) 1);
}
return panel;
}
public void updateMainPanel() {
boolean[] isVertical = model.getIsVertical();
for (int i = 0; i < isVertical.length; i ) {
String labelText = (isVertical[i]) ? "|" : "-";
leverLabel[i].setText(labelText);
}
}
private JPanel createLeverButtonPanel(String labelText, String buttonText, int index) {
JPanel panel = new JPanel(new GridBagLayout());
panel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
Font font1 = new Font("Arial Black", Font.PLAIN, 144);
Font font2 = new Font("Arial Black", Font.PLAIN, 72);
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = 0;
gbc.gridy = 0;
leverLabel[index] = new JLabel(labelText);
leverLabel[index].setFont(font1);
panel.add(leverLabel[index], gbc);
gbc.gridy ;
JButton button = new JButton(buttonText);
button.addActionListener(new AlphabetButtonListener());
button.setFont(font2);
panel.add(button, gbc);
return panel;
}
private JPanel createButtonPanel() {
JPanel panel = new JPanel(new FlowLayout());
panel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
Font font2 = new Font("Arial Black", Font.PLAIN, 48);
JButton button = new JButton("Weird Lever");
button.addActionListener(new LeverButtonListener());
button.setFont(font2);
panel.add(button);
return panel;
}
public class AlphabetButtonListener implements ActionListener {
@Override
public void actionPerformed(ActionEvent event) {
JButton button = (JButton) event.getSource();
String text = button.getText();
char c = text.charAt(0);
int index = ((int) c - 'A');
model.swap(index);
updateMainPanel();
}
}
public class LeverButtonListener implements ActionListener {
@Override
public void actionPerformed(ActionEvent event) {
// TODO Auto-generated method stub
}
}
public class PuzzleModel {
private boolean[] isVertical;
public PuzzleModel() {
int doors = 8;
this.isVertical = new boolean[doors];
reset();
}
private void reset() {
Arrays.fill(isVertical, true);
}
public void swap(int index) {
isVertical[index] = !isVertical[index];
}
public boolean[] getIsVertical() {
return isVertical;
}
}
}