Простое решение только для CSS:
.dropdown:hover>.dropdown-menu {
display: block;
}
При нажатии кнопки он все равно будет переключать на него класс show
(и останется открытым, когда больше не будет вибрировать).
Чтобы обойти это правильно , следует использовать события и свойства, зарезервированные для устройств на основе указателей: 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>
У меня также была такая же проблема, но я нашел решение. Просто создайте объект jframe
сверху и вызовите методы jframe
внизу, как jf.pack()
, jf.setVisible()
, jf.setSize()
, jf.setDefaultCloseOpetion()
должны быть в нижней части всех пользовательских интерфейсов, добавленных в этот фрейм, вы найдете он отлично работает.
Если вы хотите «обновить» 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):
repaint()
внутри EDT, так как безопасно вызывать repaint()
из любого потока, как описано здесь здесь
– nIcE cOw
17 June 2012 в 13:30
super.paintComponent()
» - Методы Paint .
– trashgod
17 June 2012 в 18:09
Взгляните на docs для JPanel.add()
, который он наследует от java.awt.Container
:
Добавляет указанный компонент в конец этого контейнера. Это удобный метод для addImpl (java.awt.Component, java.lang.Object, int). Этот метод изменяет информацию, связанную с компоновкой, и, следовательно, делает недействительной иерархию компонентов. Если контейнер уже был отображен, иерархия должна быть подтверждена после этого, чтобы отобразить добавленный компонент.
blockquote>Акцент добавлен.
Поэтому, если вы измените Контейнер после , он уже отображается, вы должны вызывать
validate()
, чтобы он отображался. Просто вызватьrepaint()
недостаточно. Возможно, вы заметили, что также работает вызовsetVisible(true)
; это потому, что он называетvalidate()
внутренне .
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);
}
}
Надеюсь, что это помогает.
С уважением.