2016-08-22 4 views
4

Текущее состояние: У меня есть объект JPanel, который содержит сложные компоненты (3D-холст, написанный мной).Показать JPanel на другом JFrame

Задача: В настоящее время имеется два экранных устройства. Я хочу использовать один для управления, другой для отображения, как и PowerPoint. Как я могу отобразить эту JPanel на другой экран эффективно (статический взгляд достаточно, но я хочу, чтобы отразить изменения на экране управления

То, что я пробовал: Я попытался сделать статическую картину в другую . JPanel каждого 200мса

  Graphics2D g2 = (Graphics2D) contentPanel.getGraphics(); 
      g2.translate(x, y); 
      g2.scale(scale, scale); 
      displayPanel.paintAll(g2); 

Примечание: ContentPanel находится в JFrame экрана дисплея, displayerPanel является панелью я хочу, чтобы скопировать

Но я получаю проблему, что на экране дисплея flicker так серьезно, что я не могу принять это ... Это проблема моего процессора или видеокарты? Или это эффективный метод, который я могу использовать? Пожалуйста, помогите, спасибо!

А вот 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); 
} 
} 
+0

Нужно ли переводить и масштабировать каждый раз при срабатывании таймера? Может быть, переименование на панели приведет к меньшему мерцанию, поскольку оно не будет включать изменение размера и т. Д. Компонента. –

+2

1) Чтобы лучше помочь, отправьте сообщение [MCVE] или [Short, Self Contained, Correct Example] (http://www.sscce.org/). 2) См. [Использование нескольких JFrames, Хорошая/Плохая Практика?] (Http://stackoverflow.com/q/9554636/418556) –

+1

Я попытался нарисовать статическую картинку в другой JPanel каждые 200 мс. - вы пытались использовать SwingTImer, потому что сигнал от TimerTask не уведомляет EDT – mKorbel

ответ

2

Вот вам пример:

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

+0

Удивительно! Он работает намного лучше, используя ваш пример! Я думаю, что SwingTimer является ключевой проблемой. Спасибо! – Bode

0

картина может быть сделано путем передачи displayPanel рисовать себя.

class DuplicatePanel extends JPanel { 
    private final JPanel displayPanel; 

    DuplicatePanel(JPanel displayPanel) { 
     this.displayPanel = displayPanel; 
    } 

    @Override 
    public void paintComponent(Graphics g) { 
     displayPanel.paintComponent(g); 
    } 
} 

для запуска перерисовки, как repaint(50L) либо использовать SwingTimer или собственные ручные перерисовки.

Смежные вопросы