[英]Can not add JComponent to JPanel
在添加從JComponent擴展到MyPanel類的類時遇到問題。 從JComboBox列表中選擇並按Start / Restart后,右側面板不會更新。 將所有繪圖內容添加到Panel MyComponent類后,即為平均值。 如果有人可以看一下並告訴我什么時候我在犯錯誤,或者是用其他不同的方式來做到這一點,請幫助我:)!
運行應用程序類:
import javax.swing.JFrame;
public class RunApp {
public static void main(String[] args) {
JFrame mainFrame = new MyPanel();
mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
mainFrame.setExtendedState(JFrame.MAXIMIZED_BOTH);
mainFrame.setVisible(true);
}
}
MyPanel類別:
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class MyPanel extends JFrame {
private JPanel leftPanel = null;
private JPanel rightPanel = null;
private JPanel mainPanel = null;
private JButton start = null;
private JButton restart = null;
private JComboBox<String> menuBox = new JComboBox<>();
private Toolkit kit = Toolkit.getDefaultToolkit();
private Dimension screenSize = kit.getScreenSize();
private int screenHeight = screenSize.height;
private int screenWidth = screenSize.width;
public MyPanel() {
mainPanel = new JPanel();
mainPanel.setBackground(Color.orange);
mainPanel.setPreferredSize(getPreferredSize());
leftPanel = new JPanel();
leftPanel.setBackground(Color.blue);
leftPanel.setPreferredSize(new Dimension(screenWidth/6, screenHeight));
menuBox.addItem("Gaussian Wave - non Dispersive");
menuBox.addItem("Gaussian Wave - Dispersive");
start = new JButton("Start");
restart = new JButton("Restart");
leftPanel.add(menuBox);
leftPanel.add(start);
leftPanel.add(restart);
rightPanel = new JPanel();
rightPanel.setBackground(Color.red);
rightPanel.setPreferredSize(new Dimension(screenWidth -( screenWidth/5 ), screenHeight));
start.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if(menuBox.getItemAt(menuBox.getSelectedIndex()).equals("Gaussian Wave - non Dispersive")) {
rightPanel.add(new MyComponent());
rightPanel.revalidate();
rightPanel.repaint();
} else if(menuBox.getItemAt(menuBox.getSelectedIndex()).equals("Gaussian Wave - Dispersive")) {
rightPanel.add(new MyComponent());
rightPanel.revalidate();
rightPanel.repaint();
}
}
});
restart.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
rightPanel.removeAll();
rightPanel.revalidate();
rightPanel.repaint();
rightPanel.setBackground(Color.RED);
}
});
mainPanel.add(leftPanel);
mainPanel.add(rightPanel);
add(mainPanel);
}
@Override
public Dimension getPreferredSize() {
return new Dimension(screenWidth, screenHeight);
}
}
就像我說的那樣,以這種方式添加MyComponent類時無法正常工作。 通常,當我直接添加此類時,例如:
public MyPanel() {
add(new MyComponent);
}
工作完美,但我想將其從列表中選擇后添加到划分的屏幕。 謝謝 !
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.geom.GeneralPath;
import java.util.function.Function;
import javax.swing.JComponent;
public class MyComponent extends JComponent {
private int wx, wy;
private double xMin, xMax, yMin, yMax, xInc, time;
private Function<Double, Double>gaussFunction;
private Function<Double, Double>dispersiveGaussFunction;
public MyComponent() {
init();
}
@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
makeGraphics(g2);
}
private void makeGraphics(Graphics2D g2) {
GeneralPath path = new GeneralPath(GeneralPath.WIND_EVEN_ODD);
if(time < 5) {
countGaussianWave(this.time);
double x = xMin;
double y = gaussFunction.apply(x);
path.moveTo(
mapX(x), mapY(y)
);
x+=xInc;
while(x < xMax) {
y = gaussFunction.apply(x);
path.lineTo(
mapX(x), mapY(y)
);
x+=xInc;
}
g2.draw(path);
repaint();
this.time+=0.001;
if(this.time > 3.5) {
this.time = -3.5;
System.out.println(time);
}
}
}
private void init() {
wx = 700;
wy = 700;
xMin = -1;
xMax = 1;
yMin = -1;
yMax = 1;
xInc = 0.01;
setTime(time);
}
private double mapX(double x) {
double fx = wx / 2;
double sx = wx / (xMax - xMin);
return x * fx + sx;
}
private double mapY(double y) {
double fy = wy / 2;
double sy = wy / (yMax - yMin);
return -y * sy + fy;
}
public void countGaussianWave(double time) {
double lambda = 1;
this.gaussFunction = x -> {
return x = Math.exp(-(Math.pow((x-time ), 2)))
* (Math.cos((2*Math.PI*(x-time))/lambda)
+ Math.sin((2*Math.PI*(x-time))/lambda)); // need complex
};
}
// public void countDispersiveGaussianWave(double time) {
//
// double lambda = 1;
// double k = (2 * Math.PI) / lambda;
//
// this.dispersiveGaussFunction = x -> {
// return x = (1/(Math.sqrt(1 + 2 * time)) *
// Math.exp(-(Math.pow((1 / Math.pow(1 + 4 * time, 2)) * (x - k * time), 2)))
// * Math.exp(Math.pow(, b));
// );
// };
// }
public double getTime() {
return time;
}
public void setTime(double time) {
this.time = time;
}
}
比較對象時不要使用“ ==”。
相反,您應該使用equals(...)
方法。
將組件添加(或刪除)到可見的GUI時,基本代碼為:
panel.add(...);
panel.revalidate();
panel.repaint();
基本上,您需要確保調用了布局管理器,否則組件的大小為(0,0),因此無需繪制任何內容。
另外,您需要重寫getPreferredSize()
方法以返回組件的大小。 否則,大小為(0,0),因此沒有要繪畫的內容。
編輯
我猜您的組件未顯示是因為您的GUI設計不佳和值的硬編碼。 FlowLayout是一種可怕的布局,用於添加到框架的所有組件。 您需要努力使用適當的布局管理器在邏輯上組織面板上的組件。 添加大量組件后,這些組件將換行到第二行。 但是,首選大小不會自動更改,因此您可能看不到所有組件。 所以
rightPanel.setPreferredSize(new Dimension(...) );
不要硬編碼首選大小。 每個組件負責確定自己的大小,這就是為什么您override
getPreferredSize()方法的原因。 這樣,布局管理者就可以正確地完成工作。 因此,擺脫所有setPreferrededSize()語句。
Jframe的默認布局是BorderLayout。 我會堅持那種布局。 不需要mainPanel,因為框架的內容窗格已經是JPanel。
因此,我將重命名您的“ leftPanel”,也許將其命名為“ topPanel”。 然后,您可以將固定組件添加到該面板並將該面板添加到框架:
JPanel topPanel = new JPanel();
topPanel.add( comboBox );
topPanel.add( startButton );
topPanel.add( restartButton );
frame.add(topPanel, BorderLayout.PAGE_START);
因此,這些組件將出現在框架的頂部。
現在也不需要“ rightPanel”。 相反,您可以直接將組件直接添加到框架中。
frame.add( new MyComponent(), BorderLayout.CENTER);
frame.revalidate();
frame.repaint();
現在,該組件將出現在框架的中央,並占用框架中所有可用的額外空間。
首先,您可以像這樣簡化“開始”按鈕的ActionListener
邏輯
if(combobox.getSelectedItem().equals("Text")
{
doSomething();
}
另外,添加或刪除新組件后,您需要調用“ 重新驗證並重新繪制”
如果你想在組件的一個油漆,確保@Override
它並調用它的超方法super.paintComponent(g);
您還將2個動作偵聽器分配給同一按鈕。 我建議刪除其中之一
連同@Camickr的重寫getPreferredSize()
方法的答案一樣,您應該將重新啟動按鈕的ActionListener
更改為此
rightPanel.removeAll();
rightPanel.revalidate();
rightPanel.repaint();
rightPanel.setBackground(Color.RED);
您可以重寫getPreferredSize();
像這樣的方法:
@Override
public Dimension getPreferredSize()
{
int width = Toolkit.getDefaultToolkit().getScreenSize().width / 2;
int height = Toolkit.getDefaultToolkit().getScreenSize().height;
return new Dimension(width, height);
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.