当前状态:
我有一个JPanel对象,其中包含复杂的组件(我自己编写的3D画布).
问题:
现在有两个屏幕设备.我想用一个用于控制,另一个用于显示,就像PowerPoint一样.如何有效地在另一个屏幕上显示此JPanel(静态视图就足够了,但我希望它反映控制屏幕上的更改?
我尝试过的:
我试图每隔200ms将静态图片绘制到另一个JPanel.
Graphics2D g2 = (Graphics2D) contentPanel.getGraphics();
g2.translate(x, y);
g2.scale(scale, scale);
displayPanel.paintAll(g2);
注意:contentPanel位于显示屏幕的JFrame中,displayerPanel是我要复制的面板
但我得到一个问题,显示屏闪烁如此严重,我不能接受这个……这是我的CPU或显卡的问题?或者这些是我可以使用的有效方法吗?请帮忙,非常感谢!
这是MCVE(对不起,这是我第一次在stackoverflow中提问,但我感动了你的帮助!再次感谢!)
import javax.swing.*;
import java.awt.*;
import java.util.*;
import java.util.Timer;
public class DisplayWindow {
private static JFrame frame = new JFrame();
private static JPanel contentPanel = new JPanel();
private static JPanel displayPanel = null;
private static Timer timerDisplay = null;
static {
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setBounds(50, 50, 1366, 768);
frame.getContentPane().add(contentPanel);
frame.setVisible(true);
if (timerDisplay == null) {
timerDisplay = new java.util.Timer();
timerDisplay.schedule(new DisplayAtFixedRate(), 1000, 250);
}
}
public static void display(JPanel panel) {
displayPanel = panel;
}
private static class DisplayAtFixedRate extends TimerTask {
@Override
public void run() {
if (displayPanel != null && displayPanel.getWidth() != 0) {
double windowWidth = frame.getWidth();
double windowHeight = frame.getHeight();
double panelWidth = displayPanel.getWidth();
double panelHeight = displayPanel.getHeight();
double scale = Math.min(windowWidth / panelWidth, windowHeight / panelHeight);
int x = (int) (windowWidth - panelWidth * scale) / 2;
int y = (int) (windowHeight - panelHeight * scale) / 2;
Graphics2D g2 = (Graphics2D) contentPanel.getGraphics();
g2.translate(x, y);
g2.scale(scale, scale);
displayPanel.paintAll(g2);
}
}
}
public static void main(String[] args) {
JFrame controlFrame = new JFrame();
controlFrame.setBounds(50, 50, 1366, 768);
JPanel controlPanel = new JPanel();
controlFrame.getContentPane().add(controlPanel, BorderLayout.CENTER);
controlPanel.add(new JLabel("Hello Stackoverflow!"));
controlFrame.setVisible(true);
DisplayWindow.display(controlPanel);
}
}
最佳答案 这是一个例子:
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTree;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
import javax.swing.WindowConstants;
public class PaintImage {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
startUI();
}
});
}
private static void startUI() {
final JFrame mainFrm = new JFrame("Main");
final JFrame paintFrame = new JFrame("Copy");
mainFrm.add(new JScrollPane(new JTree()), BorderLayout.WEST);
mainFrm.add(new JScrollPane(new JTextArea("Write your text here...")), BorderLayout.CENTER);
mainFrm.pack();
mainFrm.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
mainFrm.setLocationRelativeTo(null);
final JLabel label = new JLabel("");
paintFrame.add(label);
paintFrame.setSize(mainFrm.getSize());
paintFrame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
mainFrm.setVisible(true);
paintFrame.setVisible(true);
final Timer t = new Timer(200, new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
final Image img = getScreenShot(mainFrm.getContentPane());
label.setIcon(new ImageIcon(img));
}
});
t.start();
}
public static BufferedImage getScreenShot(Component component) {
final BufferedImage image = new BufferedImage(
component.getWidth(),
component.getHeight(),
BufferedImage.TYPE_INT_RGB
);
// call the Component's paint method, using
// the Graphics object of the image.
component.paint( image.getGraphics() ); // alternately use .printAll(..)
return image;
}
}
方法getScreenShot的来源是here