qwidget.setGeometry() 在 linux 上的位置不正确

Posted

技术标签:

【中文标题】qwidget.setGeometry() 在 linux 上的位置不正确【英文标题】:qwidget.setGeometry() incorrect position on linux 【发布时间】:2018-07-15 07:25:27 【问题描述】:

我正在尝试使用 qt 小部件覆盖 maya 的活动视图 3d。

我有一个画布基类(一个透明小部件),我可以在上面做一些绘画。它的父级是包装的 avtice 3d 视图。 一旦活动 3d 视图调整大小,就会发出 CanvasEventFilter.resize_event 信号以调整画布小部件的大小。

在 mac 和 windows 上一切正常。 但是在 linux 上,小部件是偏移的。我从 mapToGlobal() 得到的值似乎是正确的。 但是 setGeometry() 不会像我期望的那样更新小部件的位置和大小。

我在这里错过了什么?

from PySide2.QtGui import QPainter, QPen, QPainterPath
from PySide2.QtCore import Qt, QObject, Signal, Slot, QEvent, QPointF, QPoint
from PySide2.QtWidgets import QWidget, QLabel, QGridLayout
import maya.OpenMayaUI as omui
import shiboken2



class CanvasEventFilter(QObject):
    resize_event = Signal(QEvent)

    def __init__(self):
        super(CanvasEventFilter, self).__init__()

    def eventFilter(self, obj, event):
        if event.type() == QEvent.Resize:
            self.resize_event.emit(event)

        return False

class Canvas(QWidget):
    def __init__(self, parent):
        super(Canvas, self).__init__(parent=parent)
        self.setWindowFlags(Qt.FramelessWindowHint | Qt.SplashScreen | Qt.WindowStaysOnTopHint | Qt.WindowTransparentForInput)
        #  self.setAttribute(Qt.WA_TranslucentBackground)
        #  self.setAttribute(Qt.WA_NoSystemBackground)
        #  self.setAttribute(Qt.WA_PaintOnScreen)
        #  self.setAttribute(Qt.WA_TransparentForMouseEvents)

        self.canvas_event_filter = CanvasEventFilter()
        self.install_event_filter()
        self.resize()
        self.show()

    def install_event_filter(self):
        self.canvas_event_filter.resize_event.connect(self.resize)
        view_wdg = window_utils.active_view_wdg()
        view_wdg.installEventFilter(self.canvas_event_filter)

    def remove_event_filter(self):
        view_wdg = active_view_wdg()
        view_wdg.removeEventFilter(self.canvas_event_filter)

    @Slot(QEvent)
    def resize(self):
        view_wdg = active_view_wdg()
        wdg_size = view_wdg.rect()
        wdg_pos = view_wdg.pos()
        abs_pos = view_wdg.mapToGlobal(wdg_pos)
        self.setGeometry(abs_pos.x(), abs_pos.y(), wdg_size.width(), wdg_size.height())

    def __del__(self):
        self.remove_event_filter()


def active_view_wdg():
    view = omui.M3dView.active3dView()
    active_view_widget = shiboken2.wrapInstance(long(view.widget()), QWidget)
    return active_view_widget

mac 上的黑色小部件正是它预期的位置。在 linux 上是偏移量

【问题讨论】:

【参考方案1】:

这似乎对我在 Centos 7 上非常有效。 小部件在主窗口移动时跟随,并在调整主窗口大小时正确调整大小。

我不得不重命名您的 resize 方法,因为这不小心覆盖了小部件的 QtWidgets.QWidget.resize 方法(或者只需要改用 super)。而不是setGeometry,我可以简单地使用QtWidgets.QWidget.resize。我还必须删除Qt.SplashScreen,否则它无法正确关注或调整大小:

from PySide2.QtGui import QPainter, QPen, QPainterPath
from PySide2.QtCore import Qt, QObject, Signal, Slot, QEvent, QPointF, QPoint, QSize
from PySide2.QtWidgets import QWidget, QLabel, QGridLayout
import maya.OpenMayaUI as omui
import shiboken2


class CanvasEventFilter(QObject):
    resize_event = Signal(QEvent)

    def __init__(self):
        super(CanvasEventFilter, self).__init__()

    def eventFilter(self, obj, event):
        if event.type() == QEvent.Resize:
            self.resize_event.emit(event)

        return False


class Canvas(QWidget):
    def __init__(self, parent):
        super(Canvas, self).__init__(parent=parent)
        self.setWindowFlags(Qt.FramelessWindowHint  | Qt.WindowStaysOnTopHint | Qt.WindowTransparentForInput)
        self.setStyleSheet("QWidget background-color:black;")
        self.canvas_event_filter = CanvasEventFilter()
        self.install_event_filter()
        self.resize_event()
        self.show()

    def install_event_filter(self):
        self.canvas_event_filter.resize_event.connect(self.resize_event)
        view_wdg = active_view_wdg()
        view_wdg.installEventFilter(self.canvas_event_filter)

    def remove_event_filter(self):
        view_wdg = active_view_wdg()
        view_wdg.removeEventFilter(self.canvas_event_filter)

    @Slot(QEvent)
    def resize_event(self):
        view_wdg = active_view_wdg()
        wdg_size = view_wdg.rect()
        wdg_pos = view_wdg.pos()
        abs_pos = view_wdg.mapToGlobal(wdg_pos)
        self.resize(wdg_size.width(), wdg_size.height())

    def __del__(self):
        self.remove_event_filter()


def active_view_wdg():
    view = omui.M3dView.active3dView()
    active_view_widget = shiboken2.wrapInstance(long(view.widget()), QWidget)
    return active_view_widget

tool = Canvas(active_view_wdg())
tool.show()

【讨论】:

太棒了,谢谢!这解决了定位和调整大小的问题!但是,它仍然无法像在 mac 或 win 上那样工作。小部件正在调整大小,但我得到了那些奇怪的工件,就好像小部件没有正确约会一样。也许还有关于那个的想法?我也在centos7上。 !img. 我可以确认我在我的 Windows 机器上遇到了同样的刷新问题。

以上是关于qwidget.setGeometry() 在 linux 上的位置不正确的主要内容,如果未能解决你的问题,请参考以下文章

在ggplot直方图中排序计数

单词里的l啥时候不发音?有啥规律?

-L 和 -l 命令在 Makefile 中不起作用

如果 x 在集合 L 中,如何使用 lambda 函数创建返回 true 的函数 L

字母“L”的发音规则?

如何删除在 R 中不完全重复的行