在GTK中,打开新外壳后将焦点返回到文本输入 [英] In GTK, return focus to text input after opening new shell
问题描述
以下小示例在Windows和Ubuntu上的行为有所不同:
The following small example behaves differently on Windows and on Ubuntu:
-
mainShell
是Shell
包含一个Text
输入和一个Button
- 按下按钮时,将另一个
smallShell
外壳打开样式)
- 打开外壳后,焦点应返回到文本输入
mainShell
is aShell
that contains aText
input and aButton
- when the button is pressed, another shell
smallShell
isopen
ed (with a specfic style) - after the shell is opened, the focus should go back to the text input
在Windows上,焦点确实回到了文本输入。但是,在Ubuntu上,即使我们将 setActive
或 setFocus
。我希望它的行为像第一种情况一样,并产生焦点。
On windows, the focus indeed goes back to the text input. On Ubuntu, however, the smallShell
remains focussed, even though we call setActive
or setFocus
. I want it to behave like in the first case and yield the focus.
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.FocusEvent;
import org.eclipse.swt.events.FocusListener;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.MouseListener;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;
public class ShellWithoutTitleBar {
public static void main(String[] args) {
final Display display = new Display();
final Shell mainShell = new Shell(display, SWT.SHELL_TRIM);
mainShell.setSize(300, 200);
mainShell.setLayout(new GridLayout());
final Shell smallShell = new Shell(display, SWT.NO_TRIM | SWT.ON_TOP);
smallShell.setSize(150, 150);
Text text = new Text(mainShell, SWT.BORDER);
Button button = new Button(mainShell, SWT.PUSH);
button.setText("foo");
mainShell.open();
button.addMouseListener(new MouseListener() {
@Override
public void mouseDoubleClick(MouseEvent e) { }
@Override
public void mouseDown(MouseEvent e) {
smallShell.open();
mainShell.setActive();
text.setFocus();
}
@Override
public void mouseUp(MouseEvent e) { }
});
// Set up the event loop.
while (!smallShell.isDisposed()) {
if (!display.readAndDispatch()) {
// If no more entries in event queue
display.sleep();
}
}
display.dispose();
}
}
当我省略<$ c $时,一切正常c> SWT.ON_TOP 标志,但是对于我的用例而言,至关重要的是,新外壳始终位于顶部。
Everything works fine when I omit the SWT.ON_TOP
flag, however it is critical for my use case that the new shell is always-on-top.
我尝试了随机方式强制将焦点移回文本输入或至少返回主shell,但似乎没有任何作用。
I have tried random ways to forcibly give the focus back to the text input or at least the main shell but nothing seems to have any effect.
有人知道这种解决方法吗?
Does anyone know of a workaround for this? Thanks a lot in advance.
推荐答案
我找到了解决方法。关键思想是
I found a workaround. The key idea is to
- 使用
setVisible
而不是为子外壳打开---实际上,open
明确将焦点设置到子外壳程序(请参阅文档)。 - 收听SWT。激活并将焦点返回到文本字段---这不起作用,例如
- use
setVisible
instead of open for the child shell --- In fact,open
explicitly sets the focus to the child shell (see documentation). - Listen for SWT.Activate and return the focus to the text field --- This does not work e.g. with FocusListener.
这是已修复此问题的修改版。
Here's a modified version that has this issue fixed.
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.FocusEvent;
import org.eclipse.swt.events.FocusListener;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.MouseListener;
import org.eclipse.swt.events.ShellEvent;
import org.eclipse.swt.events.ShellListener;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.layout.RowLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;
public class ShellWithoutTitleBar2 {
public static void main(String[] args) {
final Display display = new Display();
final Shell mainShell = new Shell(display, SWT.SHELL_TRIM);
mainShell.setSize(300, 200);
mainShell.setLayout(new GridLayout());
mainShell.open();
final Shell overlayShell = new Shell(display, SWT.NO_TRIM | SWT.ON_TOP);
overlayShell.setSize(150, 150);
overlayShell.setLayout(new GridLayout());
Text text = new Text(mainShell, SWT.BORDER);
Button button = new Button(mainShell, SWT.PUSH);
button.setText("open overlayShell");
button.addMouseListener(new MouseListener() {
@Override public void mouseDoubleClick(MouseEvent e) { }
@Override public void mouseDown(MouseEvent e) {
// this is the one key part of the answer. we use `setVisible` instead of `open`.
overlayShell.setVisible(true);
}
@Override public void mouseUp(MouseEvent e) { }
});
// this is the other key part of the asnwer. we listen for `SWT.Activate` instead of focus or sth else.
overlayShell.addListener(SWT.Activate, (e)-> {
text.setFocus();
});
// Set up the event loop.
while (!mainShell.isDisposed()) {
if (!display.readAndDispatch()) {
// If no more entries in event queue
display.sleep();
}
}
display.dispose();
}
}
这篇关于在GTK中,打开新外壳后将焦点返回到文本输入的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!