簡體   English   中英

通過EventListener調用repaint()和/或revalidate()-Swing

[英]Calling repaint() and/or revalidate() through an EventListener - Swing

最近,我在揮桿方面遇到了一些問題。 我正在創建一個項目,該項目需要經常編輯JFrame和JPanel中的內容(在本例中為顯示在JButton上的字符串),並且想要掌握如何執行此操作。

我搜索了很長時間,發現的主要答案是我需要調用.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();
    }
}

因此,為了澄清起見,我在JPanel內,JFrame內有一個JButton。 該按鈕在其內部顯示一個字符串,該字符串最初為“ Beans”。 當我按下按鈕時,我希望字符串現在顯示為“驚奇!”。

謝謝你的時間。

您的問題是使對象與引用變量混淆,認為更改String1的文本將神奇地導致JButton顯示的文本發生變化,但這不是Java的OOP模型的工作原理。 了解JButton正在顯示String對象,該對象與String1最初引用的對象相同,但是當您更改String1引用的String時,這對原始String對象沒有影響 為了更改顯示的String,您必須通過調用JButton的setText(...)方法來更改JButton顯示的String對象,並將新的String傳遞給它。 這是唯一可行的方法。

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

    //....

在此處輸入圖片說明

順便說一句,您將要學習和使用Java命名約定 變量名都應以小寫字母開頭,而類名應以大寫字母開頭。 學習並遵循此規則將使我們能夠更好地理解您的代碼,並使您能夠更好地理解其他人的代碼。

順便提一下#2:如果您實際繪制了String,那么您的原始代碼將起作用。 請注意,在下面的代碼中,我有一個String變量currentString ,它最初引用String數組TEXTS的第一項,即字符串"One" 在JButton的ActionListener中,我將數組索引變量更新為恰當地名為index ,並將currentString變量設置為數組中的下一個String項,然后調用repaint() 該代碼起作用的原因是因為我正在繪制JPanel的繪畫方法paintComponent(...)currentString保存的文本:

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());
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM