2013-05-19 9 views
1

Я пытаюсь сделать приложение для редактирования изображений на Java с использованием шаблона проектирования MVC. Таким образом, обработка событий в контроллере, состояние и операции, относящиеся к состоянию, хранятся в моделях, и все, что видит пользователь, хранится в представлениях.Как я могу исправить эту ошибку кода?

Когда я открываю изображение, появляется окно масштабирования, которое отображает уровень масштабирования отображаемого изображения. Масштаб автоматически рассчитывается, когда он сначала отображается в paintComponent() (см. Шаг № 3). Когда я открываю изображение, я хочу, чтобы уровень масштабирования был установлен таким, каким он был рассчитан. Проблема в том, что уровень масштабирования показывает 0, и я знаю почему. Поясню:

1.ActionListenerдля открытого пункта меню обжигают

в JPSController:

class MenuBarFileOpenListener implements ActionListener { 
    public void actionPerformed(ActionEvent event) { 
     File fileChooserReturnValue = view.showAndGetValueOfFileChooser(); 

     if (fileChooserReturnValue != null) { 
      try { 
       // irrelevant code omitted 
       view.addDocument(newDocument); 
      } catch(IOException ex) { 
       ex.printStackTrace(); 
      } 
     } 
    } 
} 

2.view.addDocument()называется

Примечание: это корень проблемы

в JPSView:

public void addDocument(DocumentModel document) { 
    // irrelevant code omitted 

    // CanvasPanelView extends JPanel 
    documentsTabbedPane.add(newDocumentView.getCanvasPanelView()); 

    // THIS IS THE ROOT OF THE PROBLEM 
    double currentZoomFactor = getCurrentCanvasPanelView().getZoomFactor(); 

    // formatting the text 
    String zoomLevelText = statusBar_zoomLevelTextField_formatter.format(currentZoomFactor); 
    // setting the text of the text field 
    statusBar_zoomLevelTextField.setText(zoomLevelText); 
} 

3. Через некоторое время,paintComponent()запускается

в CanvasPanelView продолжается JPanel:

public void paintComponent(Graphics g) { 
    super.paintComponent(g); 

    if (initialRender) { 
     initialRender = false; 

     // calculates a good zoom level 
     setZoomFit(); 
    } 

    // irrelevant code omitted 

    g.drawImage(image, destinationX1, destinationY1, destinationX2, 
       destinationY2, sourceX1, sourceY1, sourceX2, sourceY2, null); 
    } 

В части 2 мы имеем следующую строку кода:

double currentZoomFactor = getCurrentCanvasPanelView().getZoomFactor(); 

Когда getZoomFactor() называется, ток CanvasPanelView не должен иметь размер, потому что она возвращает 0. Я имел эту проблему раньше, и мое решение было с этих строк кода # 3:

if (initialRender) { 
    initialRender = false; 
    setZoomFit(); 
} 

Когда paintComponent() вызывается, то CanvasPanelView должен быть дан размер, а затем, но не тогда, когда getZoomFactor() назывался. paintComponent(), и поэтому также setZoomFit(), очевидно, приходит после getZoomFactor().

Как правильно показать уровень масштабирования изображения при его открытии?

+0

Я думаю, вы можете просто добавить [ComponentListener] (HTTP: //docs.oracle.com/javase/7/docs/api/java/awt/event/ComponentListener.html), к указанному веществу и может возвращать действительную 'WIDTH/HEIGHT' соответствующего' JComponent' в разных состояниях, т. е. 'показано/скрытые/изменить размер/moved'. Таким образом, вы можете получить фактический размер, хранящийся в переменной класса, который фактически управляет состоянием 'JComponent' –

ответ

4

В принципе, у вас есть своеобразное состояние гонки (столько, сколько вы можете в одной нити).

Что происходит, вы добавляете новый вид, ожидая его немедленного выкладывания. Это не так, как это работает в Swing. Когда вы добавляете новый компонент в контейнер, выполняется запрос на обновление макетов всех компонентов в иерархии и компоновку всех тех контейнеров, которые были помечены как недействительные. Это не произойдет до тех пор, пока текущий цикл вызова не завершится, и в Диспетчерской теме событий не было времени для обработки всех запросов.

Вместо этого вы можете запланировать просмотр в более позднее время, добавив запрос в конец Диспетчер событий. Это гарантирует, что ваш запрос будет выполнен после того, как все текущие задачи на EDT будут выполнены до него (возможно, другие последуют, но вы втиснулись).

Следующий пример демонстрирует точку.

Он добавляет новую панель в JTabbedPane, выдает текущий размер, использует SwingUtilities.invokeLater, чтобы запросить обратный вызов в будущем и снова сбросить размер панелей. Вы должны найти, что первый запрос 0x0 и второй будет действительное значение (в зависимости от размера кадра и внешнего вида)

import java.awt.BorderLayout; 
import java.awt.EventQueue; 
import java.awt.GridBagLayout; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import javax.swing.JButton; 
import javax.swing.JFrame; 
import javax.swing.JLabel; 
import javax.swing.JPanel; 
import javax.swing.JTabbedPane; 
import javax.swing.SwingUtilities; 
import javax.swing.UIManager; 
import javax.swing.UnsupportedLookAndFeelException; 

public class TestTabbedPane01 { 

    public static void main(String[] args) { 
     new TestTabbedPane01(); 
    } 

    private JTabbedPane tabbedPane; 

    public TestTabbedPane01() { 
     EventQueue.invokeLater(new Runnable() { 
      @Override 
      public void run() { 
       try { 
        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); 
       } catch (ClassNotFoundException ex) { 
       } catch (InstantiationException ex) { 
       } catch (IllegalAccessException ex) { 
       } catch (UnsupportedLookAndFeelException ex) { 
       } 

       tabbedPane = new JTabbedPane(); 
       JButton btnAdd = new JButton("Add"); 
       btnAdd.addActionListener(new ActionListener() { 
        @Override 
        public void actionPerformed(ActionEvent e) { 
         final JPanel panel = new JPanel(new GridBagLayout()); 
         panel.add(new JLabel(String.valueOf(tabbedPane.getComponentCount()))); 
         tabbedPane.add(String.valueOf(tabbedPane.getComponentCount()), panel); 
         System.out.println("New Panel Size = " + panel.getSize()); 
         SwingUtilities.invokeLater(new Runnable() { 
          @Override 
          public void run() { 
           System.out.println("New Panel Size (later) = " + panel.getSize()); 
          } 
         }); 
        } 
       }); 

       JFrame frame = new JFrame("Test"); 
       frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
       frame.setLayout(new BorderLayout()); 
       frame.add(tabbedPane); 
       frame.add(btnAdd, BorderLayout.SOUTH); 
       frame.setSize(200, 200); 
       frame.setLocationRelativeTo(null); 
       frame.setVisible(true); 
      } 
     }); 
    } 


} 
+0

Большое вам спасибо! Это решило проблему. – joshreesjones

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