[英]Can't update UI on panel
如果您在下面查看我的代碼,我想做的就是修改我的addExpense()方法以生成一個新的ExpensePanel並將其添加到我的一個面板(面板3)和向量中,並更新面板3和也更新統計信息。
但是,經過無數次修改后,我似乎無法正常工作。 誰能提供一些見識?
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.Panel;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Vector;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
import javax.swing.UIManager;
class Expenses extends JFrame implements ActionListener{
ExpensesPanel widget;
public String n;
public String d;
public int c;
public int e;
public Expenses(){
// Set Dimension, size, and close operations
setSize(400,400);
setTitle("Expenses");
setDefaultCloseOperation(EXIT_ON_CLOSE);
setResizable(true);
setLocationRelativeTo(null);
// Set the look and feel of the application to that if the OS
try{
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch(Exception e){
System.out.print(e);
}
// Add Panel 1, or our main panel
JPanel p1 = new JPanel();
getContentPane().add(p1);
p1.setLayout(new BoxLayout(p1, BoxLayout.Y_AXIS));
// Add our second panel, panel 2 with a grid layout
JPanel p2 = new JPanel();
p2.setLayout(new GridLayout(4,2));
p1.add(p2);
// Add our labels
JLabel label1 = new JLabel("Name: ", JLabel.LEFT);
JTextField name = new JTextField(JTextField.EAST);
n = name.getText();
JLabel label2 = new JLabel("Date: ", JLabel.LEFT);
JTextField date = new JTextField(JTextField.EAST);
d = date.getText();
JLabel label3 = new JLabel("Cost: ", JLabel.LEFT);
JTextField cost = new JTextField(JTextField.EAST);
p2.add(label1);
p2.add(name);
p2.add(label2);
p2.add(date);
p2.add(label3);
p2.add(cost);
// Add our buttons
JButton b1 = new JButton("Add");
p2.add(b1);
JButton b2 = new JButton("Clear");
p2.add(b2);
// Set the preferred size of our windows
p2.setMaximumSize(new Dimension(Integer.MAX_VALUE, p2.getPreferredSize().height));
// Panel 3, this will hold the expenses panel
final JPanel p3 = new JPanel();
p3.setLayout(new BoxLayout(p3, BoxLayout.Y_AXIS));
JScrollPane scroll = new JScrollPane(p3);
p1.add(scroll);
// Panel 4, with a 2x2 Grid
JPanel p4 = new JPanel();
p4.setLayout(new GridLayout(2,2));
p1.add(p4);
// Add labels, and ensure they are not editable
JLabel p4l1 = new JLabel("Total", JLabel.LEFT);
JTextField p4t1 = new JTextField(JTextField.EAST);
p4t1.setEditable(false);
JLabel p4l2 = new JLabel("Average", JLabel.LEFT);
JTextField p4t2 = new JTextField(JTextField.EAST);
p4t2.setEditable(false);
p4.add(p4l1);
p4.add(p4t1);
p4.add(p4l2);
p4.add(p4t2);
// Set the preferred size to fit the rest of the window
p4.setMaximumSize(new Dimension(Integer.MAX_VALUE, p2.getPreferredSize().height));
// Action listeners for both buttons
// Action listner for button 1
b1.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e) {
System.out.println("Button 1 Clicked");
addExpense(p3);
}
});
// Action Listener for button 2
b2.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e) {
System.out.println("Button 2 Clicked");
}
});
}
public void addExpense(JPanel p3){
Vector expenseHolder = new Vector();
ExpensesPanel e = new ExpensesPanel(n, d, 2, 1);
p3.add(e);
expenseHolder.add(p3);
p3.revalidate();
}
@Override
public void actionPerformed(ActionEvent arg0) {
// TODO Auto-generated method stub
}
public static void main(String[] args){
// Main method
Expenses e = new Expenses();
// Set the application to be visible
e.setVisible(true);
}
}
class ExpensesPanel extends JPanel{
public String n;
public String d;
public int c;
public int e;
public ExpensesPanel(String name, String date, int cost, int expense){
n = name; d = date; c = cost; e = expense;
// Create new Panel and set it on horizontal axis
JPanel exp = new JPanel();
exp.setLayout(new BoxLayout(exp, BoxLayout.X_AXIS));
Box horizontalBox;
// Labels
JLabel newName = new JLabel("Name: ", JLabel.CENTER);
JLabel newDate = new JLabel("Date", JLabel.CENTER);
JLabel newCost = new JLabel("Cost: ", JLabel.CENTER);
JLabel newExp = new JLabel("Expense: ", JLabel.CENTER);
exp.add(newName, Box.createHorizontalGlue());
exp.add(newDate, Box.createHorizontalGlue());
exp.add(newCost, Box.createHorizontalGlue());
exp.add(newExp, Box.createHorizontalGlue());
}
// Override default paint component
public void paintComponent(Graphics g){
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
g2d.setBackground(Color.BLUE);
}
}
您的問題是您的ExpensePanel類具有兩個 JPanel,一個將組件添加到被調用的exp中,另一個將this
或JPanel作為類的對象,而沒有添加任何組件。 好吧,您正在向您的GUI添加第二個JPanel,因此什么也不會顯示。 還要注意,exp是在構造函數中聲明的,因此它的范圍僅限於構造函數。
一種可能的解決方案:刪除exp並將所有內容添加到this
。 請注意,您可以使用this.
這種形式的表達,例如this.add(someComponent)
可以明確顯示您的意圖,但在這種情況下,它是不必要的,並且添加的額外單詞收效甚微,因此我通常避免這樣做。
即,將您的構造函數更改為:
public ExpensesPanel(String name, String date, int cost, int expense) {
n = name;
d = date;
c = cost;
e = expense;
// Create new Panel and set it on horizontal axis
// JPanel exp = new JPanel();
setLayout(new BoxLayout(this, BoxLayout.X_AXIS));
Box horizontalBox;
// Labels
JLabel newName = new JLabel("Name: ", JLabel.CENTER);
JLabel newDate = new JLabel("Date", JLabel.CENTER);
JLabel newCost = new JLabel("Cost: ", JLabel.CENTER);
JLabel newExp = new JLabel("Expense: ", JLabel.CENTER);
add(newName, Box.createHorizontalGlue());
add(newDate, Box.createHorizontalGlue());
add(newCost, Box.createHorizontalGlue());
add(newExp, Box.createHorizontalGlue());
}
另一種可能的解決方案是保留exp JPanel,但使用getter方法將其提升為實例字段,然后讓ExpensesPanel擴展JPanel。 兩種方法都行得通,后者具有一些優點,應在以后討論(關於使用組合而不是繼承的優點)。
順便說一句,這將無濟於事:
public void paintComponent(Graphics g){
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
g2d.setBackground(Color.BLUE);
}
因為您永遠不會在更改其Color狀態后使用g2d繪制或清除(實際上是clearRect(...)
)。
更好,更容易的是調用構造函數:
setBackground(Color.blue);
問題接下來,這是錯誤的:
add(newCost, Box.createHorizontalGlue());
那不是你添加膠水的方式。 請檢查有關此內容的教程和API-您正在做大量的猜測工作,但從未成功。
除了@Hovercraft Full Of Eels答案外,您還應該通過類似以下方式更改GUI組件:
EventQueue.invokeLater(new Runnable(){
public void run()
{
//make gui change here
}
});
這將從事件調度線程(EDT)更新它。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.