Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
753 views
in Technique[技术] by (71.8m points)

qt - How to show clickable QFrame without loosing focus from main window?

Chrome like Tab in PyQt application

Finally I am able to create a chrome like tab in Qt/PyQt QMainWindow. After unsuccessfully trying to port this Qt C++ non client area painting code, I revise my thinking to be this way : trick visually by displaying a free floating QFrame that get resized and moved together with main window. Surely this is not a perfect solution (for example this code still don't solve when to disable topmost hint where the another application is on top of the main application window, but I think that's quite easy to solve)

What I want to ask in this page, is how to keep the click action on this QFrame window button from stealing focus from main window? At the moment I simply reactivate the main window when click action does occur. But it creates flashing effect on the mainwindow titlebar. I believe this SO page gives the answer, but I haven't been able to create a successful result from this C++ code:

HWND winHandle = (HWND)winId();
ShowWindow(winHandle, SW_HIDE);
SetWindowLong(winHandle, GWL_EXSTYLE, GetWindowLong(winHandle, GWL_EXSTYLE)
    | WS_EX_NOACTIVATE | WS_EX_APPWINDOW);
ShowWindow(winHandle, SW_SHOW);

Into this PyQt code:

def no_focus(self):
        import ctypes, win32con, win32gui
        dc = win32gui.GetWindowDC(self.winId())
        user32 = ctypes.windll.user32
        user32.SetWindowLongW(dc, win32con.GWL_EXSTYLE, user32.GetWindowLongW(dc, win32con.GWL_EXSTYLE) | win32con.WS_EX_NOACTIVATE | win32con.WS_EX_APPWINDOW)

Would love to let you see and test the fully functional code below:

__author__ = 'Eko Wibowo'

from PyQt4.QtGui import *
from PyQt4.QtCore import *

class FSTabHeader(QFrame):
    def __init__(self, parent):
        super(FSTabHeader, self).__init__(None)
        self.mainwindow = parent
        self.setWindowFlags(Qt.FramelessWindowHint | Qt.WindowStaysOnTopHint | Qt.SplashScreen)
        self.setFocusPolicy(Qt.NoFocus)
        self.setAttribute(Qt.WA_ShowWithoutActivating)

        layout = QHBoxLayout(self)
        layout.setSpacing(0)
        layout.setContentsMargins(0, 0, 0, 0)

        tab_text = 'Click me'
        self.btn_tab = QPushButton(self)
        self.btn_tab.setStyleSheet('border:1px')
        self.btn_tab.setContentsMargins(0,0,0,0)
        self.btn_tab.setText(tab_text)
        self.btn_tab.setMinimumHeight(25 + 1)
        self.btn_tab.setMaximumHeight(25 + 1)
        self.btn_tab.setMinimumWidth(60)
        self.btn_tab.setMaximumWidth(60)

        self.btn_tab.setCursor(Qt.PointingHandCursor)
        self.btn_tab.clicked.connect(self.dummy)

        layout.addWidget(self.btn_tab)

        self.setLayout(layout)
        self.show()

    def dummy(self):
        print 'it create flashes effect on mainwindow titlebar'
        self.mainwindow.activateWindow()

    def no_focus(self):
        import ctypes, win32con, win32gui
        dc = win32gui.GetWindowDC(self.winId())
        user32 = ctypes.windll.user32
        user32.SetWindowLongW(dc, win32con.GWL_EXSTYLE, user32.GetWindowLongW(dc, win32con.GWL_EXSTYLE) | win32con.WS_EX_NOACTIVATE | win32con.WS_EX_APPWINDOW)


    def adjust_position(self):
        top_left = self.mainwindow.mapToGlobal(self.mainwindow.rect().topLeft())
        self.move(top_left.x() + 20 + 5, top_left.y() - self.height() + 1)


class MainWindow(QMainWindow):
    def __init__(self, parent=None):
        super(MainWindow, self).__init__(parent)
        self.tab_header = FSTabHeader(self)
        self.tab_header.no_focus()

    def resizeEvent(self, *args, **kwargs):
        self.tab_header.adjust_position()

    def moveEvent(self, *args, **kwargs):
        self.tab_header.adjust_position()

if __name__ == '__main__':
    import sys
    app = QApplication(sys.argv)
    mainWindow = MainWindow(None)
    mainWindow.show()
    app.exec_()

Any suggestions?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)
Waitting for answers

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...