Current state: I have a JPanel object which contains complex components(3D-canvas written by myself).
Problem: There is two screen devices now. I want to use one for control, another just for display, just like 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?
What I have tried: I have tried to draw the static picture to another JPanel every 200ms.
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
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? 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!)
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;
}
}
Origin of method getScreenShot
is here