Swing仍然相对较新,但经过几个小时的搜索,我在网上找不到答案,因此这篇文章(如果已经回答了,很抱歉,我忽略了它)。
我正在Swing应用程序中使用JFreeChart。一些图表相对较重(180k个数据点),JFreeChart的ChartPanel需要约6秒钟才能完成第一个paintComponent()。
因此,当组件绘制时,我想在对话框中显示一条“请等待”消息(不需要使用SwingWorker显示进度)。我试图覆盖绘图组件方法,但不幸的是,该消息从未出现在屏幕上(我想线程直接绘制图表,而没有花时间绘制对话框)。
我的代码如下所示:
public class CustomizedChartPanel extends ChartPanel{
private static final long serialVersionUID = 1L;
private JDialog dialog = null;
boolean isPainted = false;
public CustomizedChartPanel(JFreeChart chart) { super(chart); }
@Override
public void paintComponent(Graphics g) {
//At first paint (which can be lengthy for large charts), show "please wait" message
if (! isPainted){
dialog = new JDialog();
dialog.setUndecorated(true);
JPanel panel = new JPanel();
panel.add(new JLabel("Please wait"));
dialog.add(panel);
dialog.pack();
GuiHelper.centerDialog(dialog); //Custom code to center the dialog on the screen
dialog.setVisible(true);
dialog.repaint();
}
super.paintComponent(g);
if (! isPainted){
isPainted = true;
dialog.dispose();
super.repaint();
}
}
}
任何关于如何解决这个问题/最佳实践的建议都将不胜感激!
谢谢,托马斯
更新:
谢谢你的提示
我开始实现建议的解决方案,因为我担心JLayer解决方案无法工作,因为它也在EDT上运行。
不幸的是,当调用器()调用paintComponent()时,我遇到了一个空指针异常。
我的代码如下所示:
@Override
public void paintComponent(Graphics graph) {
//At first paint (which can be lengthy for large charts), show "please wait" message
if (! isPainted){
isPainted = true;
dialog = new JDialog();
dialog.setUndecorated(true);
JPanel panel = new JPanel();
panel.add(new JLabel("Please wait"));
panel.add(new JLabel("Please wait !!!!!!!!!!!!!!!!!!!!!!!!!!!!!"));
dialog.add(panel);
dialog.pack();
GuiHelper.centerDialog(dialog); //Custom code to center the dialog on the screen
dialog.setVisible(true);
dialog.repaint();
RunnableRepaintCaller r = new RunnableRepaintCaller(this, graph, dialog);
SwingUtilities.invokeLater(r);
}
else super.paintComponent(graph); //NULL POINTER EXCEPTION HERE (invoked by runnable class)
}
可运行类是:
public class RunnableRepaintCaller implements Runnable{
private ChartPanel target;
private Graphics g;
private JDialog dialog;
public RunnableRepaintCaller(ChartPanel target, Graphics g, JDialog dialog){
this.target = target;
this.g = g;
this.dialog = dialog;
}
@Override
public void run() {
System.out.println(g);
target.paintComponent(g);
dialog.dispose();
}
}
再次感谢您的指点!
托马斯
我已经很久没有在Java中做任何事情了,但是据我所知,repaint()
方法实际上并不会导致任何绘图的发生。它只是将控件标记为需要在尽可能快的机会重新绘制。如果您希望立即绘制组件,您需要直接调用绘画()
方法。
您可以像这里解释的那样使用JLayer
。这是专门针对您想要的繁忙指示器的。
此外,您可以使用setEnabled(false)保持JPanel,直到数据完全加载。这样可以防止不必要的点击JPanel。
下面是一个示例,但它使用SwingWorker。您应该认真考虑使用它,因为如果操作系统以某种方式使您的框架无效,并且JFreeChart的加载是在EDT(事件调度线程)上完成的,那么您的GUI将看起来冻结。
它还允许您在处理数据时提供更好的用户反馈。(如果代码有点长,很抱歉,但大多数有趣的代码都在initUI和SwingWorker中)。
注意:您可以使用JLayer(如果使用Java 7),而不是对话框,但在我的示例中这是不必要的。
代码的灵感来自http://www.vogella.com/articles/JFreeChart/article.html
/**
* This code was directly taken from: http://www.vogella.com/articles/JFreeChart/article.html
* All credits goes to him for this code.
*
* Thanks to him.
*/
import java.util.List;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.SwingWorker;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.plot.PiePlot3D;
import org.jfree.data.general.DefaultPieDataset;
import org.jfree.data.general.PieDataset;
import org.jfree.util.Rotation;
public class PieChart extends JFrame {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
initUI();
}
});
}
protected static void initUI() {
// First we create the frame and make it visible
final PieChart demo = new PieChart("Comparison");
demo.setSize(500, 270);
demo.setVisible(true);
// Then we display the dialog on that frame
final JDialog dialog = new JDialog(demo);
dialog.setUndecorated(true);
JPanel panel = new JPanel();
final JLabel label = new JLabel("Please wait...");
panel.add(label);
dialog.add(panel);
dialog.pack();
// Public method to center the dialog after calling pack()
dialog.setLocationRelativeTo(demo);
// allowing the frame and the dialog to be displayed and, later, refreshed
SwingWorker<JFreeChart, String> worker = new SwingWorker<JFreeChart, String>() {
@Override
protected JFreeChart doInBackground() throws Exception {
publish("Loading dataset");
// simulating the loading of the Dataset
try {
System.out.println("Loading dataset");
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
// This will create the dataset
PieDataset dataset = demo.createDataset();
publish("Loading JFreeChart");
// simulating the loading of the JFreeChart
try {
System.out.println("Loading JFreeChart");
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
// based on the dataset we create the chart
JFreeChart chart = demo.createChart(dataset, "Which operating system are you using?");
// we put the chart into a panel
return chart;
}
@Override
protected void process(List<String> chunks) {
label.setText(chunks.get(0));
dialog.pack();
dialog.setLocationRelativeTo(demo);
dialog.repaint();
}
@Override
protected void done() {
try {
// Retrieve the created chart and put it in a ChartPanel
ChartPanel chartPanel = new ChartPanel(this.get());
// add it to our frame
demo.setContentPane(chartPanel);
// Dispose the dialog.
dialog.dispose();
// We revalidate to trigger the layout
demo.revalidate();
// Repaint, just to be sure
demo.repaint();
} catch (Exception e) {
e.printStackTrace();
}
}
};
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
worker.execute();
}
});
dialog.setVisible(true);
}
public PieChart(String applicationTitle) {
super(applicationTitle);
}
/** * Creates a sample dataset */
private PieDataset createDataset() {
DefaultPieDataset result = new DefaultPieDataset();
result.setValue("Linux", 29);
result.setValue("Mac", 20);
result.setValue("Windows", 51);
return result;
}
/** * Creates a chart */
private JFreeChart createChart(PieDataset dataset, String title) {
JFreeChart chart = ChartFactory.createPieChart3D(title, // chart title
dataset, // data
true, // include legend
true, false);
PiePlot3D plot = (PiePlot3D) chart.getPlot();
plot.setStartAngle(290);
plot.setDirection(Rotation.CLOCKWISE);
plot.setForegroundAlpha(0.5f);
return chart;
}
}
我在java swing中有一个UI需求,其中我需要实现以下内容: 顶部的两个按钮放在一个JPanel中。我需要画一条线通过该面板的中心,直到两个按钮的开始。下面的面板是以卡片布局排列的面板的容器。当按钮被点击时,卡片被切换显示另一个面板。 因此,在所有方面,它看起来都像一个JTabbedPane,但有一点不同,选项卡是排列在选项卡窗格中心的按钮。我需要为我正在构建的UI提供这种差异。 正如您所看
问题内容: 我想通过iText将Swing JComponent打印到pdf。 不幸的是,PDF文件中未显示任何内容。你知道如何解决这个问题吗? 问题答案: 我已经弄清楚添加addNotify和验证帮助。
问题内容: 我需要在JavaFX中创建一个对话框。我知道我可以通过修改模式,所有者和可调整大小的属性来使舞台表现得像对话框。 但是,如何从舞台窗口中隐藏“最小化”和“最大化”按钮?典型的对话框只有“关闭”按钮。 问题答案: 在Windows 7下,在显示窗口之前初始化为StageStyle.UTILITY将创建一个仅具有关闭按钮而没有最小化或最大化按钮的窗口: 如果您需要一整套基本的JavaFX对
我需要用JavaFX创建一个对话框。我知道我可以通过修改modal、owner和resizable属性使Stage的行为像一个对话框。 但是我如何从舞台窗口隐藏“最小化”和“最大化”按钮呢?典型的对话框只有“关闭”按钮。
问题内容: 我正在尝试制作绘画程序的项目中。到目前为止,我已经使用Netbeans来创建GUI并设置程序。 到目前为止,我已经能够调用在其中绘制所需的所有坐标,但是我对如何在其中实际绘制感到非常困惑。 在我的代码接近尾声时,我在面板内部进行绘制的尝试失败。 谁能在这样的示例中解释/显示如何使用图形? 我发现的所有示例都创建了一个类并对其进行扩展,JPanel但是我不知道是否可以这样做,因为它是在n
问题内容: 我在网上搜索了可拖动的Swing组件的示例,但发现示例不完整或不起作用。 我需要的是一个 Swing组件 ,可以用鼠标将其 拖动 到另一个组件中。在拖动时,它应该 已经改变 了位置,而不仅仅是“跳转”到目的地。 我将感谢没有非标准API的示例。 谢谢。 问题答案: 我提出了一个简单但可行的解决方案,我自己找到了;) 我该怎么办? 当按下鼠标时,我 在屏幕上* 记录了 光标的 位置以及