tpaviot / pythonocc-core

Python package for 3D geometry CAD/BIM/CAM
GNU Lesser General Public License v3.0
1.39k stars 379 forks source link

Encountered a problem with the display of the shapes #1303

Closed ljc0222 closed 6 months ago

ljc0222 commented 8 months ago

Dear community: I encountered a problem when I tried to display shapes of TopoDS_Shape type. It uses init_display to display Shape.If I don't use the start_display(),it seems that the graphics can be displayed correctly,but the window will be quickly closed. However,if I use start_display(), the window will blink once and become a window without shape, if I click on the window, the shape will display again! If I try to use the mouse scroll wheel to zoom in and out, it will report an error:

*Exception in Tkinter callback Traceback (most recent call last): File "C:\ProgramData\anaconda3\envs\mypythonenv3.9\lib\tkinter__init.py", line 1892, in call__ return self.func(args) File "C:\ProgramData\anaconda3\envs\mypythonenv3.9\lib\site-packages\OCC\Display\tkDisplay.py", line 62, in Zoom self._display.ZoomFactor(zoom_factor) UnboundLocalError: local variable 'zoom_factor' referenced before assignment**

I don't meet these problem when I use pythonocc-7.7.0. Now I use pythonocc-7.7.2, and my environment was created according to the official instructions. It really confused me. How can I solve this problem? This is my code. display, start_display, add_menu, add_function_to_menu = init_display() display.DisplayColoredShape(face,color=Quantity_Color(1, 0, 1, Quantity_TOC_RGB)) display.FitAll() start_display()

Thank you very much in advance for tips and help,

best regards Ljc

philosophical1337 commented 8 months ago

I had the same issue with the zoom_factor variable not being assigned. I believe this is a bug related to the way python handles scroll wheel events in windows. so solve the issue you will need to modify the tkDisplay.py file included in the module. Here is what I changed:

in the tkDisplay.py file you will find this function:

def Zoom(self, event):
        if event.num == 4:  # zoom in
            zoom_factor = 2.0
        elif event.num == 5:  # zoom out
            zoom_factor = 0.5
        self._display.ZoomFactor(zoom_factor)

if you make this change, I think you will find that the zoom function behaves as expected, it worked for me:

def Zoom(self, event):
        if event.num == 4 or event.delta > 0:  # zoom in
            zoom_factor = 2.0
        elif event.num == 5 or event.delta < 0:  # zoom out
            zoom_factor = 0.5
        self._display.ZoomFactor(zoom_factor)

as far as the issue where the display shows your model for a breif moment and then goes blank, i am having the same issue and just began looking for a solution as well.

philosophical1337 commented 8 months ago

To solve the issue of the display going blank immediately, i found that you can just install the PyQt6 module which will become recognized by pythocc-core automatically.

however, it seems like PyQt6 isnt properly implemented as I had to go into the qtDisplay.py file and make some changes. I suspect if you just install PyQt5 you will be fine but here is what I did if you are interested in PyQt6:

in the qtDisplay.py file, simply perform the following find and replace commands:

find: QtCore.Qt.LeftButton 
replace with : QtCore.Qt.MouseButton.LeftButton
find: QtCore.Qt.RightButton 
replace with : QtCore.Qt.MouseButton.RightButton
find: QtCore.Qt.MiddleButton 
replace with : QtCore.Qt.MouseButton.MiddleButton
find: QtCore.Qt.ShiftModifier: 
replace with : QtCore.Qt.KeyboardModifier.ShiftModifier:

and finally in the SimpleGui.py file I needed to change this:

find: app.exec_()
replace with : app.exec()

after all this I was able to load a .stp file and manipulate it in the viewer.

tpaviot commented 8 months ago

@philosophical1337 The Qt changes are already implemented in the current master branch. I can't remember if this was done before or after the last release.

I will test the app._exec

tpaviot commented 8 months ago

I can't see what is to replaced wih with app.exec_

philosophical1337 commented 8 months ago

what i was saying is to get it working for me, app.exec_() should be changed to app.exec() without the underscore

i only had pyqt6 installed when I was trying this as apparently it is a necessary change when going from pyqt5 to pyqt6 applications.

i found this article that describes it:

https://www.pythonguis.com/faq/pyqt5-vs-pyqt6/

.exec() or .exec()? The .exec() method in Qt starts the event loop of your QApplication or dialog boxes. In Python 2.7, exec was a keyword, meaning that it could not be used as a variable name, a function name, or a method name. In earlier versions of PyQt the method was renamed as .exec() – adding a trailing underscore – to avoid a conflict.

Python 3.0 removed the exec keyword, freeing up the name to be used. And since PyQt6 targets only Python 3.x versions, the underscored names have been removed. These were previously deprecated in PyQt5, and the .exec() method will work there too.

here at line 251 is where i made the change

            def start_display() -> None:
            win.raise_()  # make the application float to the top
            app.exec_()
tpaviot commented 8 months ago

ok I thought it was the with python keyword