Pyforms - Form appears always maximized - python

When I run my script, the main form pops-up maximized (i.e. taking all the space on my screen). I tried to set the height and width of the form using the CSS file but it did not work. I haven't seen anything about it elsewhere.
Here's my code:
import sys
import pyforms
from pyforms import BaseWidget
from pyforms.Controls import ControlText
from pyforms.Controls import ControlButton
from pyforms.Controls import ControlFile
class ImportIntoFile(BaseWidget):
def __init__(self):
super(ImportIntoFile,self).__init__('HTCondor & EnergyPlus')
self._Input = ControlFile('Input')
self._Output = ControlFile('Output')
self._Import = ControlButton('Import')
self._Close = ControlButton('Close')
self._formset = ['',(' ','_Input',' '),(' ','_Output',' '),('','_Close','','_Import',''),'']
self._Import.value = self.__ImportAction
self._Close.value = self.__CloseAction
def __ImportAction(self):
OutputFile = open(self._Output.value,'a')
InputFile = open(self._Input.value,'r')
OutputFile.close
InputFile.close
def __CloseAction(self):
sys.exit()
if __name__ == "__main__": pyforms.startApp( ImportIntoFile )`

You can pass a window geometry to the pyforms.start_app() call. So something like the code below should work.
if __name__ == "__main__":
pyforms.start_app( ImportIntoFile, geometry=(200, 200, 400, 400) )

I had the same problem. Pyforms uses Qt, so some of these modules will be familiar, and this css will modify them.
I used:
QMainWindow{
max-width:500px;
max-height:500px;
}
to successfully set the size of the main window, but you can't increase the size later, so if all you want is a fixed size window, it works.

I can't find a good solution too. For temporary workaround when I want to avoid maximized by default, what I did is modifying C:\Python27\Lib\site-packages\pyforms\gui\standaloneManager.py.
From
if geometry is not None:
w.show()
w.setGeometry(*geometry)
else:
w.showMaximized()
To
if geometry is not None:
w.show()
w.setGeometry(*geometry)
else:
w.showNormal()

Related

PyQgis: item is not the expected type on a QgsMapCanvas

I am currently working on a PyQgis based standalone application and I need to add various QgsRubberBand to my Canvas.
I made a subclass of it : LineAnnotation.
The problem is that when I use the method "QgsMapCanvas.itemAt(event.pos() )" on a "canvasPressEvent", it returns a "qgis._gui.QgsRubberBand" object, not a "LineAnnotation".
Did I do something wrong ? The rest of my program can't work if it doesn't recognize that it's a LineAnnotation as it contains several new methods that I need to use.
Also I can't interact with the item at all, if I try to use one of the methods from QgsRubberBand, the application crashes.
Here is the code with the problem:
from qgis.gui import QgsMapCanvas, QgsLayerTreeMapCanvasBridge, QgsRubberBand
from qgis.core import QgsApplication, QgsProject, QgsPointXY, QgsGeometry
from qgis.PyQt.QtGui import QColor
import sys
class LineAnnotation(QgsRubberBand):
def __init__(self, canvas):
QgsRubberBand.__init__(self, canvas)
self.setColor(QColor("red") )
self.setWidth(10)
class Interface(QgsMapCanvas):
def __init__(self):
QgsMapCanvas.__init__(self)
self.setCanvasColor(QColor("#182F36") )
project_path = "project_path"
project = QgsProject.instance()
project.read(project_path)
layer_tree = QgsLayerTreeMapCanvasBridge(project.layerTreeRoot(), canvas=self)
layer_tree.setAutoSetupOnFirstLayer(False)
self.zoomToFeatureExtent(project.mapLayersByName('layer_name')[0].extent() )
self.enableAntiAliasing(True)
self.setAcceptDrops(True)
self.setParallelRenderingEnabled(True)
p1 = QgsPointXY(524670.46860305720474571, 5470375.41737424582242966)
p2 = QgsPointXY(589864.10151600651443005, 5487531.63656186405569315)
r = LineAnnotation(self)
r.setToGeometry(QgsGeometry.fromPolylineXY([p1, p2]) )
def mousePressEvent(self, event) -> None:
item = self.itemAt(event.pos() )
print(type(item) )
# Output is "<class 'qgis._gui.QgsRubberBand'>"
# Expected: "<class 'LineAnnotation'>"
class StackOverflow:
def __init__(self):
qgs = QgsApplication([], True)
qgs.setDoubleClickInterval(250)
qgs.initQgis()
graphicUI = Interface()
graphicUI.showMaximized()
sys.exit(qgs.exec_() )
if __name__ == '__main__':
app = StackOverflow()
> output: \<class 'qgis.\_gui.QgsRubberBand'\>
> Desired output: \<class 'lineAnnotation.LineAnnotation'\>
Problem seems to occur in versions prior to Qgis 3.26, my problem was solved after updating to latest version (3.28).

File dialog always returns alpha order

I'm creating an application which plots data in files. The first file plotted defines the origin to which all other data is transformed relative to. AFAICT, the QFileDialog always returns files in alphabetical order, regardless of selection order.
Is there a way to return the data ordered by selection?
To illustrate, create a folder with files named something A, B, C or 1, 2, 3. Regardless of the manner they're selected or appear in File Name line edit, the list of paths returned is in alphabetical order.
import os
import sys
from PyQt5 import QtCore, QtWidgets
MYDIR = (os.environ['USERPROFILE'] + '/Desktop/numbered').replace("\\", "/")
def on_button_pressed():
paths, _ = QtWidgets.QFileDialog.getOpenFileNames(
directory = MYDIR,
caption='Open',
filter=(
'All (*.*)'
))
for i, path in enumerate(paths):
print(i, path, flush=True)
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
button = QtWidgets.QPushButton("Open")
button.pressed.connect(on_button_pressed)
button.show()
sys.exit(app.exec_())
EDIT An implementation of #musicamate's response which may hang:
import os
import sys
from PyQt5 import QtCore, QtWidgets
MYDIR = (os.environ['USERPROFILE'] + '/Desktop/numbered').replace("\\", "/")
class SelectionOrderFileDialog(QtWidgets.QFileDialog):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.setOption(QtWidgets.QFileDialog.DontUseNativeDialog)
self.setFileMode(QtWidgets.QFileDialog.ExistingFiles)
self.setWindowFlags(self.windowFlags() & ~QtCore.Qt.WindowContextHelpButtonHint)
list_view = self.findChild(QtWidgets.QListView, 'listView')
self.selection_model = list_view.selectionModel()
self.selection_model.selectionChanged.connect(self.check_selection)
self.current_selection = []
def check_selection(self):
active_selection = []
for index in self.selection_model.selectedRows():
path = index.data(QtWidgets.QFileSystemModel.FilePathRole)
active_selection.append(path)
updated_current_selection = []
for path in self.current_selection:
if path in active_selection:
updated_current_selection.append(path)
active_selection.remove(path)
updated_current_selection.extend(active_selection)
self.current_selection[:] = updated_current_selection
print(self.current_selection, flush=True)
def on_button_pressed():
# Works fine when called as...
# dialog = SelectionOrderFileDialog()
# Causes hangs on Open
dialog = SelectionOrderFileDialog(
directory = MYDIR,
caption='Open',
filter=(
'text (*.txt)'
';;python (*.py)'
';;All (*.*)'
))
dialog.exec_()
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
button = QtWidgets.QPushButton("Open")
button.resize(300, 25)
button.pressed.connect(on_button_pressed)
button.show()
sys.exit(app.exec_())
Such level of control cannot be achieved by using static methods, but it can be done by using an instance of QFileDialog.
The only requirement is to avoid the native dialog, so that we can access one of the file views (a non-native QFileDialog has a list view and a tree view), and then connect to the selectionChanged signal of its selection model.
Then, everytime the signal is emitted, we check with the current ordered selection, remove paths that already exist and build a new list by extending with the new elements.
def showDialog(self):
def checkSelection():
selection = []
for index in selectionModel.selectedRows():
path = index.data(QtWidgets.QFileSystemModel.FilePathRole)
selection.append(path)
newOrderedPaths = []
for path in orderedPaths:
if path in selection:
newOrderedPaths.append(path)
selection.remove(path)
newOrderedPaths.extend(selection)
orderedPaths[:] = newOrderedPaths
dialog = QtWidgets.QFileDialog(self)
dialog.setOption(dialog.DontUseNativeDialog)
dialog.setFileMode(dialog.ExistingFiles)
listView = dialog.findChild(QtWidgets.QListView, 'listView')
selectionModel = listView.selectionModel()
selectionModel.selectionChanged.connect(checkSelection)
orderedPaths = []
dialog.exec_()
print(orderedPaths)
Obviously, the same can be done using a subclass.

How to get absolute path from popup (Intent.ACTION_OPEN_DOCUMENT_TREE) kivy , andoid -11

I am a beginner programmer, writing my first application in kivy. And ran into limited storage issue for android - 11 (API 30). How to get the absolute path from the pop-up window when the user selects the folder to save the application data in which I am going to store some data. My application works fine without this choice on 9 anroid, but here's the problem.
here is the minimal code from that window. How to get the absolute path 'root_id' for further manipulations with this folder. By creating files in it and opening SaveDialoga in kivy
from kivy.uix.label import Label
import os
from android import activity, mActivity
from jnius import autoclass
from kivy.app import App
from jnius import cast
from android.storage import app_storage_path, primary_external_storage_path, secondary_external_storage_path
Intent = autoclass('android.content.Intent')
DocumentsContract = autoclass('android.provider.DocumentsContract')
Document = autoclass('android.provider.DocumentsContract$Document')
class Demo(App):
REQUEST_CODE = 42 # unique request ID
def set_intent(self):
intent = Intent(Intent.ACTION_OPEN_DOCUMENT_TREE)
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
mActivity.startActivityForResult(intent, self.REQUEST_CODE)
def intent_callback(self, requestCode, resultCode, intent):
if requestCode == self.REQUEST_CODE:
msg = ""
root_uri = intent.getData()
print(root_uri.getPath())
# /tree/primary:CarInWay
root_id = DocumentsContract.getTreeDocumentId(root_uri)
print( root_id)
# primary:CarInWay
from pathlib import Path
p = Path(root_uri.getPath()).resolve()
print(p, p.is_dir(), p.is_absolute())
# /tree/primary:CarInWay False True
p = Path(root_id).resolve()
print( p, p.is_dir(), p.is_absolute())
# /data/data/car.carinway/files/app/primary:CarInWay False True
primary_ext_storage = primary_external_storage_path()
data_dir = str(os.path.join(primary_ext_storage, 'CarInWay'))
check_data_dir = os.path.exists(data_dir)
print(data_dir , check_data_dir)
# /storage/emulated/0/CarInWay === True
p = Path(primary_ext_storage + '/CarInWay')
print('===', p, '===', p.stat().st_mode)
# /storage/emulated/0/CarInWay === 16832
settings_path = app_storage_path()
secondary_ext_storage = secondary_external_storage_path()
print(settings_path, primary_ext_storage, secondary_ext_storage)
# /data/user/0/car.carinway/files /storage/emulated/0 None
def on_start(self):
self.set_intent()
def build(self):
activity.bind(on_activity_result=self.intent_callback)
self.label = Label()
return self.label
if __name__ == '__main__':
Demo().run()
Sorry for the not quite accurate postal question. But my problem is saving the data in non-application folders, so that when the application is updated, they are not overwritten.
The solution to the problem turned out to be simple.
context = autoclass('android.content.Context')
path_file = context.getExternalFilesDir(None)
path = path_file.getAbsolutePath()
Which made it possible to create a folder in ANDROID / DATA. Where can I already create and store data.

Find the last window created in Maya?

I was wondering if there is any way to find the name of the last window created in Maya, knowing that I can't add any information to the window itself before that... I checked in both the cmds and API but couldn't find anything. Maybe in PyQt but I don't know much about it.
I'm looking for any solution. Thanks
you can work with something like a close callback, save the needed information and restore it again
def restoreLayout(self):
"""
Restore the layout of each widget
"""
settings=self.settings
try:
self.restoreGeometry(settings.value("geometry").toByteArray())
self.restoreState(settings.value("windowState").toByteArray())
size=settings.value('fontSize').toFloat()[0]
self.setFontSize(size)
except:
pass
def saveLayout(self):
"""
Save the layout of each widget
Save the main window id to your data base
"""
settings=self.settings
settings.setValue("geometry", self.saveGeometry())
settings.setValue("windowState", self.saveState())
settings.setValue("fontSize", app.font().pointSize())
def closeEvent(self, event):
QtGui.QMainWindow.closeEvent(self, event)
self.saveLayout()
a simple case/idea to save tha main win_id and a child button_id:
from functools import partial
import json
def close_ui(*args):
win_id = args[0]
if cmds.window(win_id, exists=True):
cmds.deleteUI(win_id, window=True)
with open('dataBase/ui/uidata.json', 'w') as outfile:
json.dump(args, outfile)
win = {}
win["main_win"] = cmds.window()
cmds.columnLayout()
cmds.text( label='closing it' )
win["btn"] = cmds.button( label='Close')
cmds.button(win["btn"],e=True, command=partial(close_ui, win["main_win"], win["btn"]))
cmds.showWindow(win["main_win"])
Here is what I came up with, it's surely not the "cleanest" solution but it works!
# List all the currently opened windows
uisBefore = cmds.lsUI (wnd = True)
# Execute the function which may or may not create a window
func(*args, **kwargs)
# List all the opened windows again
uisAfter = cmds.lsUI (wnd = True)
# Find all the windows that were opened after executing func()
newUIs = [ui for ui in uisAfter if ui not in uisBefore]
If you create a window with the window command, you'll get back the name of the window you just created:
import maya.cmds as cmds
w = cmds.window()
c= cmds.columnLayout()
def who_am_i(*_):
print "window is", w
b = cmds.button('push', c=who_am_i)
cmds.showWindow(w)
If for some reason you don't own the code that creates the window:
existing_windows = set(cmds.lsUI(type = 'window'))
// make your window here
new_windows = list(set(cmds.lsUI(type = 'window') - existing_windows))

how do I correctly pass my pathL and pathR to load my images in opencv?

I am new to python and I am using opencv. I have one button(btn_Convertir) that calls the method sustractBands that calls the method createImage, but it receives two parameters, the paths from two images that I am loading using QFileDialog. I want to pass the two paths as parameters in order to use imread from opencv, and I also want to use my methods createImageRed and createCyan, but I always get an error, how can I do it in python? Please help
this is my code
import sys
from PyQt4 import QtGui, uic, QtCore
import cv2
import numpy as np
class Window(QtGui.QMainWindow):
def __init__(self):
super(Window, self).__init__()
uic.loadUi('UI.ui', self)
self.cb_tipos.addItems(["a", "b", "c"])
self.show()
self.abrir_izq.clicked.connect(self.openFileL)
self.abrir_der.clicked.connect(self.openFileR)
self.rb_matrices.clicked.connect(self.cambiarEstadoCombo)
self.btn_Convertir.clicked.connect(self.sustractBands, pathL, pathR)
def openFileL(self):
pathL = QtGui.QFileDialog.getOpenFileName(self, "Open image","",'Images (* .jpg)')
pixmap = QtGui.QPixmap(pathL)
print self.im_izq.size()
pixmap.scaled(self.im_izq.size(), QtCore.Qt.IgnoreAspectRatio, QtCore.Qt.FastTransformation)
self.im_izq.setPixmap(pixmap)
def openFileR(self):
pathR = QtGui.QFileDialog.getOpenFileName(self, "Open image","",'Images (* .jpg)')
pixmapd = QtGui.QPixmap(pathR)
pixmapd.scaled(self.im_der.size(), QtCore.Qt.KeepAspectRatio, QtCore.Qt.FastTransformation)
self.im_der.setPixmap(pixmapd)
def createImage(imgL, imgR):
imgFinal = createImageRed(imgL) + createImageCyan(imgR)
cv2.imwrite('Final.jpg', imgFinal)
cv2.imshow("Finished", imgFinal)
cv2.waitKey()
def createImageRed(imgL):
imgL[:, :, 0] = 0
imgL[:, :, 1] = 0
return imgL
def createImageCyan(imgR):
imgR[:, :, 2] = 0
return imgR
def sustractBands(self, pathL, pathR):
imgL = cv2.imread(pathL, cv2.IMREAD_COLOR)
imgR = cv2.imread(pathR, cv2.IMREAD_COLOR)
createImage(imgL, imgR)
if __name__ == '__main__':
app = QtGui.QApplication(sys.argv)
window = Window()
sys.exit(app.exec_())
When you call a method you have to prefix it with the object you want to call it. Here the object is self, so instead of simply calling createImage(imgL, imgR) you have to call it like this self.createImage(imgL, imgR) same things for createImageRed and createImageCyan
as noted as a comment to this answer you still have undefined names pathL and pathR you must replace them by self.pathL and self.pathR in the openFile* methods and in the sustractBands, not using them as parameters of substractBands and finaly connecting it with
self.btn_Convertir.clicked.connect(self.sustractBands)
It's because the variables are by default locals to the methods and to be able to go out of a method you have to, in order or goodness either return them, use attribute (which I did) or declare them as global

Categories