После вызова JTabbedPane.removeAll () у JTabbedPane все еще есть x вкладок?

StackOverflow https://stackoverflow.com/questions/1013479

  •  06-07-2019
  •  | 
  •  

Вопрос

В моем JTabbedPane я удаляю вкладки двумя различными способами:

tabbedPane.remove(index)

и

tabbedPane.removeAll()

Оба отлично работают с точки зрения закрытия вкладок. Однако в моем TabbedPane есть прослушиватель изменений, который вызывает другой модуль, чтобы сообщить об изменениях вкладок. Вот где проблема.

При добавлении и удалении вкладок с помощью remove (index) исходный TabbedPane в методе stateChanged () содержит правильное количество вкладок при проверке tabbedPane. getTabCount () .

Тем не менее, при вызове tabbedPane.getTabCount () после tabbedPane.removeAll () счетчик остается тем же счетчиком, который присутствовал непосредственно перед removeAll ( ) .

У кого-нибудь есть предложения?

Это было полезно?

Решение

После просмотра исходного кода я вижу, что происходит.

JTabbedPane запускает ChangeEvents при изменении выбранной вкладки. Но чтобы удалить все вкладки, сначала для выбранной вкладки устанавливается значение -1, а , а затем - для удаления всех вкладок. Поэтому, когда ChangeListener ловит событие, все вкладки все еще там.

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

while (myTabbedPane.getTabCount() > 0)
    myTabbedPane.remove(0);

Другие советы

Вот, пожалуйста. вместо этого используйте ContainerListener:

import java.awt.event.ContainerEvent;
import java.awt.event.ContainerListener;

import javax.swing.JPanel;
import javax.swing.JTabbedPane;

import junit.framework.TestCase;

public class JTabbedPaneTest extends TestCase {
    private JTabbedPane pane;
    private int         count   = 0;

    protected void setUp() throws Exception {
        pane = new JTabbedPane();
        ContainerListener containerListener = new ContainerListener() {
            public void componentAdded(ContainerEvent e) {
                count++;
            }

            public void componentRemoved(ContainerEvent e) {
                count--;
            }
        };
        pane.addContainerListener(containerListener);
        JPanel panel1 = new JPanel();
        JPanel panel2 = new JPanel();
        pane.add(panel1);
        pane.add(panel2);
    }

    public void testOne() throws Exception {
        assertEquals(2, count);
        assertEquals(2, pane.getTabCount());
        pane.remove(0);
        pane.remove(0);
        assertEquals(0, count);
        assertEquals(0, pane.getTabCount());
    }

    public void testMany() throws Exception {
        assertEquals(2, count);
        assertEquals(2, pane.getTabCount());
        pane.removeAll();
        assertEquals(0, count);
        assertEquals(0, pane.getTabCount());
    }
}

При поиске кода JTabbedPane (версия 6) оба кода проходят через removeTabAt , что должно уменьшить количество. Однако, вероятно, оно будет запускать событие для каждой вкладки, что означает, что первое событие должно иметь getTabCount () на единицу меньше, чем число перед removeAll () .

Вы уверены в вызове getTabCount () ? Что произойдет, если вы удалите все вкладки (с конца) вручную?

Попробуйте позвонить в проверить или перепроверить

Вот контрольный пример, который помогает выявить проблему.

import javax.swing.JPanel;
import javax.swing.JTabbedPane;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

import junit.framework.TestCase;

public class JTabbedPaneTest extends TestCase {
    private JTabbedPane     pane;
    private int             count = 0;

    protected void setUp() throws Exception {
        pane = new JTabbedPane();
        ChangeListener listener = new ChangeListener() {
            public void stateChanged(ChangeEvent e) {
                JTabbedPane pane = (JTabbedPane)e.getSource();
                int before = count;
                count = pane.getTabCount();
                System.out.println(String.format("%s --> %s", before, count));
            }
        };
        pane.addChangeListener(listener);
        JPanel panel1 = new JPanel();
        JPanel panel2 = new JPanel();
        pane.add(panel1);
        pane.add(panel2);
    }

    public void testOne() throws Exception {
        assertEquals(1, count); // I actually expect 2
        assertEquals(2, pane.getTabCount());
        pane.remove(0);
        pane.remove(0);
        assertEquals(0, count);
        assertEquals(0, pane.getTabCount());
    }

    public void testMany() throws Exception {
        assertEquals(1, count); // I actually expect 2
        assertEquals(2, pane.getTabCount());
        pane.removeAll();
        assertEquals(2, count); // I actually expect 0
        assertEquals(0, pane.getTabCount());
    }
}

Я думаю, что проблема синхронизации происходит; вывод:

0 --> 1
1 --> 1
1 --> 0
0 --> 1
1 --> 2

Похоже, что некоторые события изменений теряются.

Обновление : оставить это для потомков, но это неправильно; как отмечает mmyers, события запускаются только при изменении выбора.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top