Вызов repaint () и / или revalidate () через EventListener - Swing - PullRequest
0 голосов
/ 25 сентября 2018

У меня были некоторые проблемы со свингом в последнее время.Я создаю проект, который требует редактирования вещей (в данном случае строки, отображаемой на JButton) внутри JFrame и JPanel довольно часто, и я хотел бы понять, как это сделать.

Iискал долго, и основной ответ, который я нашел, заключается в том, что мне нужно вызвать .repaint (), возможно, после того, как я вызову .revalidate ().Однако мне не удалось заставить мой код работать правильно.

Прямо сейчас, рамка будет рисоваться изначально так, как должна, но после нажатия кнопки текст внутри нее не изменится - фактически, она создает большой журнал ошибок, который можно просмотреть здесь: https://pastebin.com/7P85cB8h

ниже мой код:

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class Actions extends JFrame implements ActionListener
{
    JButton Beans;
    String String1;
    JPanel things;

    public static void main (String[] args)
    {
        new Actions();
    }

    public Actions()
    {
        JPanel things = new JPanel();
        String1 = "Beans";

        this.setSize(400,400);
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.setTitle("Hello there");

        Box theBox = Box.createHorizontalBox();

        Beans = new JButton("" + String1);
        Beans.addActionListener(this);

        theBox.add(Box.createHorizontalStrut(50));
        theBox.add(Beans);

        this.add(theBox);

        setVisible(true);
    }

    public void actionPerformed(ActionEvent e)
    {
        String1 = "Surprise!";
        things.revalidate();
        things.repaint();
    }
}

Итак, чтобы уточнить, у меня есть JButton, внутри JPanel, внутри JFrame.Кнопка отображает строку внутри себя, которая изначально гласит «Бобы».Когда я нажимаю кнопку, я хочу, чтобы строка теперь гласила «Сюрприз!».

Спасибо за ваше время.

1 Ответ

0 голосов
/ 25 сентября 2018

Ваша проблема заключается в том, что вы путаете объект со ссылочной переменной, думая, что изменение текста String1 волшебным образом приведет к изменению текста, отображаемого JButton, но это не то, как работает модель ООП Java.Поймите, что JButton отображает объект String, тот же объект, на который изначально ссылается String1, но затем, когда вы изменяете строку, на которую ссылается String1, это не влияет на исходный объект String .Чтобы изменить отображаемую строку, вы должны изменить объект String, отображаемый JButton, вызвав метод setText(...) JButton и передать в него новую строку.Это единственный способ, которым это будет работать.

public void actionPerformed(ActionEvent e) {
    Beans.setText("Surprise!");
}

См. Комментарии:

// here are several reference variables
// all without assigned objects, and thus
// all holding "null" values:
JButton Beans;
String String1;
JPanel things;


public Actions()  {
    //..... 

    // here you assign the String object, "Beans" to the String1 variable
    String1 = "Beans";

    // .....

    // here you create a JButton and pass in String1's current object, "Beans"
    // into the constructor (note the "" + is NOT needed for Strings, only for numberrs)
    Beans = new JButton("" + String1);

    //.....
}

public void actionPerformed(ActionEvent e)  {
    // here you change the object that String1 refers to
    String1 = "Surprise!";

    // but this has no effect on the original String object, "Beans" displayed in the
    // JButton, but rather all it does is change the state of String1. 
    // To change the state of the JButton, you must explicitly do this 
    // by calling setText on it

    //....

enter image description here

В сторону, вы будетехочу изучать и использовать Соглашения об именах Java .Имена переменных должны начинаться со строчной буквы, а имена классов - с заглавной.Изучение этого и последующее это позволит нам лучше понять ваш код и позволит вам лучше понять код других.

Обратите внимание, как отрывок №2: Если вы на самом деле рисуете Строка, тогда ваш оригинальный код будет работать.Обратите внимание, что в приведенном ниже коде у меня есть строковая переменная currentString, которая первоначально ссылается на первый элемент в массиве строк TEXTS, String "One".В ActionListener JButton я обновляю переменную индекса массива с точным именем index, устанавливаю переменную currentString для следующего элемента String в массиве и затем вызываю repaint().Этот код работает потому, что я рисую текст, удерживаемый currentString в методе рисования JPanel, paintComponent(...):

import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;

import javax.swing.*;

public class DrawStringPanel extends JPanel {
    private static final String[] TEXTS = {
            "One", "Two", "Three", "Four", "Five", 
            "Six", "Seven", "Eight", "Nine", "Ten"
            };
    private static final int PREF_W = 400;
    private static final int PREF_H = PREF_W;
    private static final Font TEXT_FONT = new Font(Font.SANS_SERIF, Font.BOLD, 40);
    private static final int TEXT_X = 150;
    private static final int TEXT_Y = 200;
    private int index = 0;

    // Note that this String variable holds the first item in the TEXTS array
    private String currentString = TEXTS[index];

    public DrawStringPanel() {
        setPreferredSize(new Dimension(PREF_W, PREF_H));
        JButton nextBtn = new JButton("Next");
        add(nextBtn);
        nextBtn.addActionListener(e -> {
            // update the array index
            index++;  // get next index
            index %= TEXTS.length;  // but don't let get bigger then array length

            // and in the ActionListener here I'm changing the variable and calling repaint
            // this works because this variable is actually painted within this JPanel's 
            // paintComponent method....
            currentString = TEXTS[index];
            repaint();
        });
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        Graphics2D g2 = (Graphics2D) g;
        g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
        g2.setFont(TEXT_FONT);

        // ****** HERE ****** I draw the contents of the currentString variable
        g2.drawString(currentString, TEXT_X, TEXT_Y);
    }

    private static void createAndShowGui() {
        DrawStringPanel mainPanel = new DrawStringPanel();

        JFrame frame = new JFrame("DrawStringPanel");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.getContentPane().add(mainPanel);
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> createAndShowGui());
    }
}
...