Как прокрутить два JTextPane's? - PullRequest
8 голосов
/ 17 июня 2011

Я новичок в Swing, использующий NetBeans. Я хочу вертикально прокрутить два JTextPane бок о бок. Прокрутка должна быть синхронизирована и выполнена с помощью одной полосы прокрутки.

Если я добавлю JTextPanes из конструктора NetBean, они автоматически помещаются в JScrollPane, поэтому они прокручиваются независимо. Я удалил вмещающие панели прокрутки и поместил их в JPanel вместо этого, чтобы JPanel мог быть клиентом единственной JScrollPane. Это похоже на работу, за исключением того, что когда JTextPanes очень длинные, они, кажется, идут за концом JPanel. Я могу прокрутить панель и обе текстовые панели до определенной точки. Достигнув дна, я могу навести курсор на одну из текстовых панелей и стрелку вниз за пределами поля зрения.

Вот код из моего основного метода. Я скопировал макет из чего-то, сгенерированного конструктором NetBeans.

java.awt.EventQueue.invokeLater(new Runnable() {
    public void run() {
topFrame aTopFrame = new topFrame();
JScrollPane scollBothDiffs = new javax.swing.JScrollPane();
JPanel bothDiffsPanel = new javax.swing.JPanel();
JTextPane leftDiffPane = diffPane1;
JTextPane rightDiffPane = diffPane2;


javax.swing.GroupLayout bothDiffsPanelLayout = new javax.swing.GroupLayout(bothDiffsPanel);
bothDiffsPanel.setLayout(bothDiffsPanelLayout);
bothDiffsPanelLayout.setHorizontalGroup(
    bothDiffsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
    .addGroup(bothDiffsPanelLayout.createSequentialGroup()
        .addGap(20, 20, 20)
        .addComponent(leftDiffPane, javax.swing.GroupLayout.PREFERRED_SIZE, 463, javax.swing.GroupLayout.PREFERRED_SIZE)
        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
        .addComponent(rightDiffPane, javax.swing.GroupLayout.PREFERRED_SIZE, 463, javax.swing.GroupLayout.PREFERRED_SIZE)
        .addContainerGap(52, Short.MAX_VALUE))
);
bothDiffsPanelLayout.setVerticalGroup(
    bothDiffsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
    .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, bothDiffsPanelLayout.createSequentialGroup()
        .addContainerGap()
        .addGroup(bothDiffsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
            .addComponent(rightDiffPane, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, 630, Short.MAX_VALUE)
            .addComponent(leftDiffPane, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, 630, Short.MAX_VALUE))
        .addContainerGap())
);

scollBothDiffs.setViewportView(bothDiffsPanel);

javax.swing.GroupLayout layout = new javax.swing.GroupLayout(aTopFrame.getContentPane());
aTopFrame.getContentPane().setLayout(layout);
layout.setHorizontalGroup(
    layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
    .addGroup(layout.createSequentialGroup()
        .addGap(20, 20, 20)
        .addComponent(scollBothDiffs, javax.swing.GroupLayout.DEFAULT_SIZE, 997, Short.MAX_VALUE)
        .addContainerGap())
);
layout.setVerticalGroup(
    layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
    .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
        .addContainerGap()
        .addComponent(scollBothDiffs, javax.swing.GroupLayout.DEFAULT_SIZE, 671, Short.MAX_VALUE)
        .addContainerGap())
);

aTopFrame.pack();
aTopFrame.setVisible(true);
}
});

Вот изображение, которое показывает мою реализацию первого ответа, где текстовые панели не ограничены горизонтальной областью отображения. Image showing text panes that are too wide for the horizontal display area

И на этом изображении показаны текстовые панели, ограниченные в горизонтальной области отображения, но в этом примере исходная проблема заключается в отсутствии прокрутки по вертикали, если текстовые панели очень длинные. Image showing text panes that are bounded horizontally

Ответы [ 2 ]

15 голосов
/ 17 июня 2011

Уловка, которую я использовал ранее, состоит в том, чтобы использовать две JScrollPanes, скрыть вертикальную полосу прокрутки для левой панели и установить ее модель в качестве модели для правой панели прокрутки. Таким образом, когда пользователь прокручивает правую полосу прокрутки, он обновляет обе панели прокрутки, поскольку они используют одну и ту же модель. Вот пример, который также имеет двойную синхронизированную горизонтальную полосу прокрутки внизу:

JTextPane leftDiffPane = diffPane1;
JTextPane rightDiffPane = diffPane2;
JScrollPane spLeft = new JScrollPane(leftDiffPane, JScrollPane.VERTICAL_SCROLLBAR_NEVER, JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
JScrollPane spRight = new JScrollPane(leftDiffPane, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
spLeft.getHorizontalScrollBar().setModel(spRight.getHorizontalScrollBar().getModel());
spLeft.getVerticalScrollBar().setModel(spRight.getVerticalScrollBar().getModel());

// ...

Обратите внимание, что это может работать не так хорошо, если ваши JTextPanes имеют разные размеры (я не пробовал, но, скорее всего, это вызовет проблемы)

Также можно исправить прокрутку колеса мыши, перенаправив события колеса с левой панели прокрутки на правую:

spLeft.setWheelScrollingEnabled(false);
spLeft.addMouseWheelListener(new MouseWheelListener() {
    public void mouseWheelMoved(MouseWheelEvent e) {
        spRight.dispatchEvent(e);
    }
});
4 голосов
/ 17 июня 2011

Если вы используете GridLayout для обоих ваших JTextPane, а затем оберните его JScrollPane, полоса прокрутки будет для обоих JTextPanes, так как GridLayout будет разделен на прямоугольники одинакового размера.

Примерно так должно работать (проверено на Java 6)

// Text Panes initialization. I am just setting text so you can see
// what each pane is.
JTextPane leftDiffPane = new JTextPane();
leftDiffPane.setText("left");
JTextPane rightDiffPane = new JTextPane();
rightDiffPane.setText("right");

// Wrap the Text Panes with a Panel since you can only
// have a single component within a scroll pane.      
JPanel bothDiffsPanel = new JPanel();
bothDiffsPanel.setLayout(new GridLayout(1, 2));
bothDiffsPanel.add(leftDiffPane, BorderLayout.WEST);
bothDiffsPanel.add(rightDiffPane, BorderLayout.EAST);

// Fill in the frame with both of the panels.
setLayout(new BorderLayout());
add(new JScrollPane(bothDiffsPanel), BorderLayout.CENTER);

Если вы используете описанный выше подход, если при изменении текста в JTextPanes размеры будут переполнены, появится полоса прокрутки, а при использовании будет прокручиваться оба компонента. Если изменение текста переполняет компонент, он будет прокручиваться вниз, чтобы ваш ввод был виден.

Надеюсь, это поможет!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...