【问题标题】:In GTK, return focus to text input after opening new shell在 GTK 中,打开新 shell 后将焦点返回到文本输入
【发布时间】:2020-07-21 17:34:11
【问题描述】:

以下小示例在 Windows 和 Ubuntu 上的行为不同:

  • mainShell 是一个 Shell,它包含一个 Text 输入和一个 Button
  • 按下按钮时,另一个外壳 @9​​87654325@ 是 opened(具有特定样式)
  • shell打开后,焦点应该回到文本输入

在 Windows 上,焦点确实回到了文本输入。然而,在 Ubuntu 上,smallShell 仍然是焦点,即使我们调用 setActivesetFocus。我希望它表现得像第一种情况并产生焦点。

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();
  }

}

当我省略 SWT.ON_TOP 标志时,一切正常,但是对于我的用例来说,新的 shell 始终处于顶层是至关重要的。

我尝试了随机方式将焦点强制返回到文本输入或至少主 shell,但似乎没有任何效果。

有人知道解决方法吗?提前非常感谢。

【问题讨论】:

    标签: java eclipse-plugin gtk swt


    【解决方案1】:

    我找到了解决方法。关键思想是

    1. 使用setVisible 而不是为子shell open --- 事实上,open 明确地将焦点设置到子shell (see documentation)。
    2. 监听 SWT.Activate 并将焦点返回到文本字段 --- 这不起作用,例如使用 FocusListener。

    这是修复了此问题的修改版本。

    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();
      }
    
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-12-04
      • 2015-10-04
      • 2019-08-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多