最近我在挥杆方面遇到了一些问题。我正在创建一个项目,该项目需要非常频繁地在JFrame和JPanel中编辑内容(在本例中为显示在JButton上的字符串),并且想掌握如何做到这一点。
我搜索了很长时间,发现的主要答案是,可能需要在调用.revalidate()之后调用.repaint()。但是,我一直无法使我的代码正常运行。
现在,框架将按原样绘制,但是按下按钮时,框架中的文本不会改变-实际上,它会产生较大的错误日志,可在此处查看: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”。当我按下按钮时,我希望字符串现在显示为“惊喜!”。
感谢您的宝贵时间。
答案 0 :(得分:4)
您的问题是将对象与引用变量混淆的一种方式,认为更改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 naming conventions。变量名都应以小写字母开头,而类名应以大写字母开头。学习并遵循此规则将使我们能够更好地理解您的代码,并使您能够更好地理解其他人的代码。
请注意第二点:如果您实际上 绘制 字符串,那么您的原始代码就可以使用。注意,在下面的代码中,我有一个String变量currentString
,它最初引用String数组TEXTS
中的第一项,即String "One"
。在JButton的ActionListener中,我更新名为index
的数组索引变量,并将currentString
变量设置为数组中的下一个String项,然后调用repaint()
。该代码起作用的原因是因为我正在JPanel的绘制方法currentString
中绘制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());
}
}