首页 > 解决方案 > qwidget.setGeometry() 在 linux 上的位置不正确

问题描述

我正在尝试使用 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上它是偏移的

标签: pythonqtpysidemaya

解决方案


这在 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()

推荐阅读