I need help to translate a dialog box in pyqt5 - pyqt5

I'm working with Python 3.7 and PyQt 5 under windows and linux. I do not have problems translating classes that inherit Qapplication, but I do not know how to do it with QDialog ...
This works fine:
if __name__ == "__main__":
app = QtWidgets.QApplication([])
t = QtCore.QTranslator(app)
t.load('my_app_fr.qm')
app.installTranslator(t)
calc = CalculatorGui()
calc.show()
app.exec_()
But with app = QtWidgets.QDialog() I don't know how proceed because installTranslator() is not an attribute of QDialog()

Related

Setting the view of a scene via mlab in traitsui is not working

I am trying to code a program based on traitsUI and Mayavi, but I have some problems. Following the code I am using:
#!/usr/bin/env python
import os
from traits.api import HasTraits, Instance, String, on_trait_change
from traitsui.api import View, Item
from tvtk.pyface.scene_editor import SceneEditor
from mayavi.tools.mlab_scene_model import MlabSceneModel
from mayavi.core.ui.mayavi_scene import MayaviScene
class ActorViewer(HasTraits):
scene = Instance(MlabSceneModel, ())
view = View(Item(name='scene',
editor=SceneEditor(scene_class=MayaviScene),
show_label=True,
resizable=True,
dock='tab',
height=500,
width=500),
resizable=True
)
def __init__(self, engine=None, **traits):
HasTraits.__init__(self, **traits)
if engine is not None:
self.scene=MlabSceneModel(engine=engine)
else:
self.scene=MlabSceneModel()
self.generate_data()
#on_trait_change('scene.activated')
def generate_data(self):
src=self.scene.mlab.pipeline.open(Path+i)
self.scene.mlab.view(40, 50)
self.scene.mlab.pipeline.outline(src)
self.scene.mlab.pipeline.iso_surface(src, contours=60, opacity=0.5)
if __name__ == '__main__':
Path = "/path/to/my/folder"
filelist = os.listdir(Path)
for i in filelist:
if i.endswith(".vtr"):
if ("E1_" in i) or ("E2_" in i):
print("file name ", i)
a = ActorViewer()
a.configure_traits()
The call self.scene.mlab.view(40, 50) returns AttributeError: 'NoneType' object has no attribute 'active_camera', thus I don't know how to set the camera. I have read that it is related to when the scene is activated, but I couldn't find a solution.
Without setting the view, the code works, but each file is loaded and rendered alone. In order to proceed with the main loop, each render has to be closed. I would like to dock each of the file without closing them.
I couldn't find a way to set a custom label to each tab after allowing show_label=True and to have it aligned horizontally at the top of the scene.
I tried to set the outline with the 'cornered' layout, but I couldn't find a way to do that. self.scene.mlab.pipeline.outline.outline_mode('cornered') gets simply ignored.
Thank you for your help!

How do I change the dropEvent behavior correctly?

I am trying to change the default behavior when dropping a file in QtextEdit
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_Dialog(object):
def setupUi(self, Dialog):
Dialog.setObjectName("Dialog")
Dialog.resize(869, 499)
self.verticalLayout = QtWidgets.QVBoxLayout(Dialog)
self.verticalLayout.setObjectName("verticalLayout")
self.horizontalLayout = QtWidgets.QHBoxLayout()
self.horizontalLayout_2 = QtWidgets.QHBoxLayout()
self.horizontalLayout_2.setObjectName("horizontalLayout_2")
self.textEdit = QtWidgets.QTextEdit(Dialog)
self.textEdit.setObjectName("textEdit")
self.horizontalLayout_2.addWidget(self.textEdit)
self.verticalLayout.addLayout(self.horizontalLayout_2)
self.textEdit.setAcceptDrops(True)
self.textEdit.dropEvent = self.dropEvent
def dropEvent(self, event):
event.setDropAction(QtCore.Qt.CopyAction)
if event.mimeData().hasText():
print(event.mimeData().text())
event.accept()
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
Dialog = QtWidgets.QDialog()
ui = Ui_Dialog()
ui.setupUi(Dialog)
Dialog.show()
sys.exit(app.exec_())
But after performing dropEvent, the cursor in TextEdit stops moving.
What am I missing?
QTextEdit uses internal flags (not exposed to the API) that properly update the text cursor during drag and drop operations, mostly to allow pasting in the exact position within the text based on the mouse cursor, and in the meantime show the "cursor caret" to the user so that they will know where the content would be inserted.
This means that the default implementation of QTextEdit dropEvent() must always be called in order to properly update the cursor.
Now, proper drag&drop implementation of QTextEdit should always be done through insertFromMimeData() (and eventually canInsertFromMimeData() to prevent drop at all).
If you want to alter the behavior when dropping certain contents, then just override that function:
from PyQt5 import QtWidgets
class DropEdit(QtWidgets.QTextEdit):
def insertFromMimeData(self, data):
if data.hasUrls():
self.insertPlainText('%ONEFILE%')
else:
super().insertFromMimeData(data)
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
test = DropEdit()
test.show()
sys.exit(app.exec_())
Now, the issue is that insertFromMimeData() is called no matter if the operation is done from clipboard (through Ctrl+V or via the context menu) or from drag&drop. Another issue is that drag&drop can also happen within the text edit, for instance to move a selected text somewhere else.
A basic solution, which would prevent pasting from d&d but not from clipboard, would be to use an internal flag that can be set in the dropEvent() and would be cleared in insertFromMimeData().
The following example will accept drops only if the dropped data has no urls in it, but will still accept pasting from clipboard if it contains urls (for instance, copying an object in the file browser):
class DropEdit(QtWidgets.QTextEdit):
acceptDrop = True
def insertFromMimeData(self, data):
if self.acceptDrop:
super().insertFromMimeData(data)
self.acceptDrop = True
def dropEvent(self, event):
self.acceptDrop = not event.mimeData().hasUrls()
super().dropEvent(event)

Fault in my resource file or resource import for PyQt5?

I'm new to working with PyQt for GUI development. As a tutorial for one of the trainings, I'm to develop a phone dialer, which basically just displays a number pad and makes the appropriate dial tones when pressed. This involves importing a resource file that contains the 12 tones. i downloaded the tones from the internet and tested them. They all work just fine. however after I create the resource file, and convert it using pyrcc5, the tones do not play. I've copied the resources.py from the tutorial and the dial pad works as expected. I'm wondering if anyone can help me debug this issue. I haven't seen anything online that shows a similar problem.
if someone can help me attach files, I can add the resource files to the question as well.
Here is a copy of my code although it doesn't appear to be the problem:
import sys
from PyQt5 import QtWidgets as qtw
from PyQt5 import QtCore as qtc
from PyQt5 import QtMultimedia as qtmm
import resources1
class SoundButton(qtw.QPushButton):
def __init__(self, wav_file, *args, **kwargs):
super().__init__(*args, **kwargs)
self.wav_file = wav_file
self.player = qtmm.QSoundEffect()
self.player.setSource(qtc.QUrl.fromLocalFile(wav_file))
self.clicked.connect(self.player.play)
class MainWindow(qtw.QMainWindow):
def __init__(self):
"""MainWindow constructor.
This widget will be our main window.
We'll define all the UI components in here.
"""
super().__init__()
# Main UI code goes here
dialpad = qtw.QWidget()
self.setCentralWidget(dialpad)
dialpad.setLayout(qtw.QGridLayout())
for i, symbol in enumerate('123456789*0#'):
button = SoundButton(f':/dtmf/{symbol}.wav', symbol)
row = i // 3
column = i % 3
dialpad.layout().addWidget(button, row, column)
# End main UI code
self.show()
if __name__ == '__main__':
app = qtw.QApplication(sys.argv)
# it's required to save a reference to MainWindow.
# if it goes out of scope, it will be destroyed.
mw = MainWindow()
sys.exit(app.exec())
Thanks in advance for your help

Cannot open exe created by cx_freeze

I tried converting my keras and nltk chatbot to exe using cx_freeze. When I clicked on the exe, it gave me the following error:
Error window
How can I correct this error?
Also, here's my setup.py code:
import sys
from cx_Freeze import setup, Executable
build_exe_options = {"includes": ["tkinter"]}
base = None
if sys.platform == "win32":
base = "Win32GUI"
setup(
name = "NAB",
version = "3",
description = " ",
options = {"build_exe": build_exe_options},
executables = [Executable("nab3.py", base = base)])
Btw, my chatbot code works perfectly fine when i run it seperately.
If anyone knows what this error means and how to correct it, please do help me out.
Thanks in advance:)

Moving a QGraphicsProxyWidget with ItemIgnoresTransformations after changing QGraphicsView scale

I have a QGraphicsScene that contains multiple custom QGraphicsItems. Each item contains a QGraphicsProxyWidget which itself contains whatever widgets are needed by the business logic. The proxy has a Qt::Window flag applied to it, so that it has a title bar to move it around. This is all working well, except when moving a proxy widget when the view has been scaled.
The user can move around the scene à la google maps, ie by zooming out then zooming in back a little farther away. This is done with calls to QGraphicsView::scale. Items should always be visible no matter the zoom value, so they have the QGraphicsItem::ItemIgnoresTransformations flag set.
What happens when moving a proxyWidget while the view has been scaled is that on the first move event the widget will jump to some location before properly being dragged.
I had this issue with Qt5.7.1, and could reproduce it with PyQt5 as it is simpler to reproduce and hack around, please see the snippet below.
Steps to reproduce:
move the widget around, notice nothing unusual
use the mouse wheel to zoom in or out. The higher the absolute scale, the higher the effect on the issue.
click on the widget, and notice how it jumps on the first moving of the mouse.
Snippet:
import sys
import PyQt5
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import QApplication, QWidget, QVBoxLayout, QPushButton
from PyQt5.QtWidgets import QGraphicsScene, QGraphicsView, QGraphicsProxyWidget, QGraphicsWidget, QGraphicsObject
global view
global scaleLabel
def scaleScene(event):
delta = 1.0015**event.angleDelta().y()
view.scale(delta, delta)
scaleLabel.setPlainText("scale: %.2f"%view.transform().m11())
view.update()
if __name__ == '__main__':
app = QApplication(sys.argv)
# create main widget
w = QWidget()
w.resize(800, 600)
layout = QVBoxLayout()
w.setLayout(layout)
w.setWindowTitle('Example')
w.show()
# rescale view on mouse wheel, notice how when view.transform().m11() is not 1,
# dragging the subwindow is not smooth on the first mouse move event
w.wheelEvent = scaleScene
# create scene and view
scene = QGraphicsScene()
scaleLabel = scene.addText("scale: 1")
view = QGraphicsView(scene)
layout.addWidget(view)
view.show();
# create item in which the proxy lives
item = QGraphicsWidget()
scene.addItem(item)
item.setFlag(PyQt5.QtWidgets.QGraphicsItem.ItemIgnoresTransformations)
item.setAcceptHoverEvents(True)
# create proxy with window and dummy content
proxy = QGraphicsProxyWidget(item, Qt.Window)
button = QPushButton('dummy')
proxy.setWidget(button)
# start app
sys.exit(app.exec_())
The jump distance is:
proportional to the scaling of the view , and to the distance of the mouse from the scene origin
goes from scene position (0,0) towards the mouse position (I think)
might be caused by the proxy widget not reporting the mouse press/move properly. I'm hinted at this diagnostic after looking at QGraphicsProxyWidgetPrivate::mapToReceiver in qgraphicsproxywidget.cpp (sample source), which does not seem to take scene scaling into account.
I am looking for either
confirmation that this is an issue with Qt and I did not misconfigured the proxy.
an explanation on how fix the mouse location given by the proxy to its children widgets (after installing a eventFilter)
any other workaround
Thanks
Almost 2 years later I got back to this issue again, and finally found a solution. Or rather a workaround, but a simple one at least. It turns out I can easily avoid getting into the issue with local/scene/ignored transforms in the first place.
Instead of parenting the QGraphicsProxyWidget to a QGraphicsWidget, and explicitly setting the QWidget as proxy target, I get the proxy directly from the QGraphicsScene, letting it set the window flag on the wrapper, and set the ItemIgnoresTransformations flag on the proxy. Then (and here's the workaround) I install an event filter on the proxy, intercept the GraphicsSceneMouseMove event where I force the proxy position to currentPos+mouseDelta (both in scene coordinates).
Here's the code sample from above, patched with that solution:
import sys
import PyQt5
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import *
global view
global scaleLabel
def scaleScene(event):
delta = 1.0015**event.angleDelta().y()
view.scale(delta, delta)
scaleLabel.setPlainText("scale: %.2f"%view.transform().m11())
view.update()
class ItemFilter(PyQt5.QtWidgets.QGraphicsItem):
def __init__(self, target):
super(ItemFilter, self).__init__()
self.target = target
def boundingRect(self):
return self.target.boundingRect()
def paint(self, *args, **kwargs):
pass
def sceneEventFilter(self, watched, event):
if watched != self.target:
return False
if event.type() == PyQt5.QtCore.QEvent.GraphicsSceneMouseMove:
self.target.setPos(self.target.pos()+event.scenePos()-event.lastScenePos())
event.setAccepted(True)
return True
return super(ItemFilter, self).sceneEventFilter(watched, event)
if __name__ == '__main__':
app = QApplication(sys.argv)
# create main widget
w = QWidget()
w.resize(800, 600)
layout = QVBoxLayout()
w.setLayout(layout)
w.setWindowTitle('Example')
w.show()
# rescale view on mouse wheel, notice how when view.transform().m11() is not 1,
# dragging the subwindow is not smooth on the first mouse move event
w.wheelEvent = scaleScene
# create scene and view
scene = QGraphicsScene()
scaleLabel = scene.addText("scale: 1")
view = QGraphicsView(scene)
layout.addWidget(view)
view.show();
button = QPushButton('dummy')
proxy = scene.addWidget(button, Qt.Window)
proxy.setFlag(PyQt5.QtWidgets.QGraphicsItem.ItemIgnoresTransformations)
itemFilter = ItemFilter(proxy)
scene.addItem(itemFilter)
proxy.installSceneEventFilter(itemFilter)
# start app
sys.exit(app.exec_())
Hoping this may help someone who's ended up in the same dead end I was :)