JPanel не появится до изменения размера [дубликат]

Простое решение только для CSS:

.dropdown:hover>.dropdown-menu {
  display: block;
}

При нажатии кнопки он все равно будет переключать на него класс show (и останется открытым, когда больше не будет вибрировать).

< hr>

Чтобы обойти это правильно , следует использовать события и свойства, зарезервированные для устройств на основе указателей: jQuery mouseenter, mouseleave и :hover. Должно работать гладко, интуитивно, хотя и не мешать вообще тем, как выпадающее меню работает на сенсорных устройствах. Попробуйте, дайте мне знать, если это сработает для вас:

Complete, jQuery + CSS solution ( touch нетронутый):

$('body').on('mouseenter mouseleave','.dropdown',function(e){
  var _d=$(e.target).closest('.dropdown');_d.addClass('show');
  setTimeout(function(){
    _d[_d.is(':hover')?'addClass':'removeClass']('show');
    $('[data-toggle="dropdown"]', _d).attr('aria-expanded',_d.is(':hover'));
  },300);
});
.dropdown:hover>.dropdown-menu {
  display: block;
}

$('body').on('mouseenter mouseleave','.dropdown',function(e){
  var _d=$(e.target).closest('.dropdown');
  _d.addClass('show');
  setTimeout(function(){
    _d[_d.is(':hover')?'addClass':'removeClass']('show');
    $('[data-toggle="dropdown"]', _d).attr('aria-expanded',_d.is(':hover'));
  },300);
});
.dropdown:hover>.dropdown-menu {
  display: block;
}
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.6/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://code.jquery.com/jquery-3.1.1.slim.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/tether/1.4.0/js/tether.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.6/js/bootstrap.min.js"></script>

<nav class="navbar navbar-toggleable-md navbar-light bg-faded">
  <button class="navbar-toggler navbar-toggler-right" type="button" data-toggle="collapse" data-target="#navbarNavDropdown" aria-controls="navbarNavDropdown" aria-expanded="false" aria-label="Toggle navigation">
    <span class="navbar-toggler-icon"></span>
  </button>
  <a class="navbar-brand" href="#">Navbar</a>
  <div class="collapse navbar-collapse" id="navbarNavDropdown">
    <ul class="navbar-nav">
      <li class="nav-item active">
        <a class="nav-link" href="#">Home <span class="sr-only">(current)</span></a>
      </li>
      <li class="nav-item">
        <a class="nav-link" href="#">Features</a>
      </li>
      <li class="nav-item">
        <a class="nav-link" href="#">Pricing</a>
      </li>
      <li class="nav-item dropdown">
        <a class="nav-link dropdown-toggle" href="http://example.com" id="navbarDropdownMenuLink" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
          Dropdown link
        </a>
        <div class="dropdown-menu" aria-labelledby="navbarDropdownMenuLink">
          <a class="dropdown-item" href="#">Action</a>
          <a class="dropdown-item" href="#">Another action</a>
          <a class="dropdown-item" href="#">Something else here</a>
        </div>
      </li>
    </ul>
  </div>
</nav>

16
задан John 17 June 2012 в 09:35
поделиться

4 ответа

У меня также была такая же проблема, но я нашел решение. Просто создайте объект jframe сверху и вызовите методы jframe внизу, как jf.pack(), jf.setVisible(), jf.setSize(), jf.setDefaultCloseOpetion() должны быть в нижней части всех пользовательских интерфейсов, добавленных в этот фрейм, вы найдете он отлично работает.

0
ответ дан alamoot 21 August 2018 в 14:30
поделиться

Если вы хотите «обновить» JPanel, тогда вы должны вызвать repaint (), который вызовет ваш paintComponent (). Это должно устранить вашу проблему:

public void setImage(BufferedImage bi)
{
    image = bi;
    EventQueue.invokeLater(new Runnable()
    {
        public void run()
        {
            repaint();
        }
    });
}

Хорошая практика обновления и изменения GUI с помощью EDT. Heres больше информации об EDT, если вам интересно:

Как работает поток отправки событий?

repaint не требуется вызванный из EDT. Если вы меняете GUI, например, устанавливаете текст в JLabel, он должен быть внутри EDT. Heres больше информации о том, что можно назвать вне EDT (любезно предоставлено nIcE cOw):

Безопасно использовать Component.repaint () вне EDT?

7
ответ дан Community 21 August 2018 в 14:30
поделиться
  • 1
    Спасибо, Джон, он отлично работает! – nautilusvn 17 June 2012 в 09:52
  • 2
    +1 для ценного ввода. Просто предложение, не нужно помещать вызов repaint() внутри EDT, так как безопасно вызывать repaint() из любого потока, как описано здесь здесь – nIcE cOw 17 June 2012 в 13:30
  • 3
    «подклассы компонентов Swing, которые имеют делегат UI ... должны вызывать super.paintComponent()» - Методы Paint . – trashgod 17 June 2012 в 18:09

Взгляните на docs для JPanel.add(), который он наследует от java.awt.Container:

Добавляет указанный компонент в конец этого контейнера. Это удобный метод для addImpl (java.awt.Component, java.lang.Object, int). Этот метод изменяет информацию, связанную с компоновкой, и, следовательно, делает недействительной иерархию компонентов. Если контейнер уже был отображен, иерархия должна быть подтверждена после этого, чтобы отобразить добавленный компонент.

Акцент добавлен.

Поэтому, если вы измените Контейнер после , он уже отображается, вы должны вызывать validate(), чтобы он отображался. Просто вызвать repaint() недостаточно. Возможно, вы заметили, что также работает вызов setVisible(true); это потому, что он называет validate() внутренне .

7
ответ дан Nateowami 21 August 2018 в 14:30
поделиться
  • 1
    Я получаю лучшие результаты с помощью revalidate(). validate() выполняет эту работу, но не изменяет размеры, чтобы добавить новые компоненты. – Chameleon 28 May 2018 в 07:12

У меня была та же проблема и исправлена ​​ее вызовом setVisible (true); JFrame I.

Пример: если ваш JFrame не обновляется после использования:

jframe.setContentPane(new MyContentPane());

исправить его с помощью:

jframe.setContentPane(new MyContentPane());
jframe.setVisible(true);

Я знаю что это звучит глупо, даже если ваш JFrame уже виден, но это единственный способ, который я нашел до сих пор, чтобы исправить эту проблему (предложенное выше решение не сработало для меня).

Вот полный пример. Запустите его, а затем раскомментируйте «f.setVisible (true)»; инструкции в классах Panel1 и Panel2, и вы увидите разницу. Не забывайте импортировать (Ctrl + Shift + O для автоматического импорта).

Основной класс:

public class Main {
    private static JFrame f;
    public static void main(String[] args) {
        f = new JFrame();
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.setContentPane(new Panel1(f));
        f.pack();    
        f.setVisible(true);
    }
}

Класс Panel1:

public class Panel1 extends JPanel{
    private JFrame f;
    public Panel1(JFrame frame) {
        f = frame;
        this.setLayout(new BoxLayout(this, BoxLayout.LINE_AXIS));
        JButton b = new JButton("Panel 1");
        b.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                f.setContentPane(new Panel2(f));
                // Uncomment the instruction below to fix GUI "update-on-resize-only" problem
                //f.setVisible(true);
            }
        });
        add(b);
    }
}

Класс Panel2:

public class Panel2 extends JPanel{
    private JFrame f;
    public Panel2(JFrame frame) {
        f = frame;
        this.setLayout(new BoxLayout(this, BoxLayout.LINE_AXIS));
        JButton b = new JButton("Panel 2");
        b.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                f.setContentPane(new Panel1(f));
                // Uncomment the instruction below to fix GUI "update-on-resize-only" problem
                //f.setVisible(true);
            }
        });
        add(b);
    }
}

Надеюсь, что это помогает.

С уважением.

2
ответ дан user2154283 21 August 2018 в 14:30
поделиться
  • 1
    Отлично! Не знаю, почему это работает, но это единственное, что решило мою проблему. До этого я делал это: Размер размера = frame.getSize (); Boolean maximized = frame.getExtendedState () == JFrame.MAXIMIZED_BOTH; frame.setSize (новый размер ((int) size.getWidth () - 1, (int) size.getHeight () - 1)); if (maximized) frame.setExtendedState (JFrame.MAXIMIZED_BOTH); else frame.setSize (размер); Ваш ответ намного, намного чище и менее хаки. Благодаря! – dberm22 15 January 2014 в 03:44
  • 2
Другие вопросы по тегам:

Похожие вопросы: