[英]Display JPanel on another JFrame
Current state: I have a JPanel object which contains complex components(3D-canvas written by myself). 当前状态:我有一个JPanel对象,其中包含复杂的组件(我自己编写的3D画布)。
Problem: There is two screen devices now. 问题:现在有两个屏幕设备。 I want to use one for control, another just for display, just like PowerPoint.
我想用一个用于控制,另一个用于显示,就像PowerPoint一样。 How can I display this JPanel on another screen efficiently(static view is enough, but I want it to reflect the change on control screen?
如何有效地在另一个屏幕上显示此JPanel(静态视图就足够了,但我希望它反映控制屏幕上的更改?
What I have tried: I have tried to draw the static picture to another JPanel every 200ms. 我试过的:我试图每隔200ms将静态图片绘制到另一个JPanel。
Graphics2D g2 = (Graphics2D) contentPanel.getGraphics();
g2.translate(x, y);
g2.scale(scale, scale);
displayPanel.paintAll(g2);
Notes: contentPanel is in a JFrame of display screen, displayerPanel is the panel I want to copy 注意: contentPanel位于显示屏幕的JFrame中,displayerPanel是我要复制的面板
But I get a problem that the display screen flicker so seriously that I can not accept this...Is it the problem of my CPU or graphics card? 但我得到一个问题,显示屏闪烁如此严重,我不能接受这个......这是我的CPU或显卡的问题? Or is these any efficient method I can use?
或者这些是我可以使用的有效方法吗? Please help, thanks so much!
请帮忙,非常感谢!
And here is the MCVE (sorry, this is my first time asking question in stackoverflow, but I am touched by your helps! Thanks again!) 这是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);
}
}
Here is an example for you: 这是一个例子:
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;
}
}
The painting can be done by passing the displayPanel to draw itself. 可以通过传递displayPanel来绘制自己来完成绘画。
class DuplicatePanel extends JPanel {
private final JPanel displayPanel;
DuplicatePanel(JPanel displayPanel) {
this.displayPanel = displayPanel;
}
@Override
public void paintComponent(Graphics g) {
displayPanel.paintComponent(g);
}
}
To trigger the repaints, like repaint(50L)
either use a SwingTimer
or your own manual repaints. 要重新触发重绘,例如
repaint(50L)
,请使用SwingTimer
或您自己的手动重绘。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.