LINUX.ORG.RU

Как в питоне получить N значений из кутешного окна?

 ,


0

2

По ходу моего знакомства с фрикадом возник вопрос, как в скрипты передавать параметры из GUI. К сожалению, скрипты там на дурацком питоне, который я вообще не знаю.

Для получения N параметров я накатал такую штуку:

def getNparametersFromWindow(Labels, Title="Tell me more"):
	RET = 0
	Parameters = []
	def hide():
		RET = 1
		del Parameters[:]
		dialog.hide()
	def proceed():
		RET = 1
		dialog.hide()
	dialog = QtGui.QDialog()
#	dialog.resize(200,300)
	dialog.setWindowTitle(Title)
	la = QtGui.QVBoxLayout(dialog)
	lbl = []
	for i in range(0, len(Labels)):
		lbl.append(QtGui.QLabel(Labels[i]))
		la.addWidget(lbl[i])
		Parameters.append(QtGui.QLineEdit())
		la.addWidget(Parameters[i])
	okbox = QtGui.QDialogButtonBox(dialog)
	okbox.setOrientation(QtCore.Qt.Horizontal)
	okbox.setStandardButtons(QtGui.QDialogButtonBox.Cancel|QtGui.QDialogButtonBox.Ok)
	la.addWidget(okbox)
	QtCore.QObject.connect(okbox, QtCore.SIGNAL("accepted()"), proceed)
	QtCore.QObject.connect(okbox, QtCore.SIGNAL("rejected()"), hide)
	QtCore.QMetaObject.connectSlotsByName(dialog)
	dialog.show()
	while (RET != 1):
		pass
	return Parameters
Однако, она подвисает - ничего не происходит.

Вопрос: чего нужно изменить, чтобы эта функция возвращала строковой массив из N введенных пользователем значений, соответствующих меткам из массива Labels?

☆☆☆☆☆

А где QApplication? Без него event-loop просто не стартует. Скорее всего, поэтому и висит.

А ещё: QFormLayout тебе нужен.

А ещё: dialog.hide() не нужен в слотах, ибо при нажатии на Окей или Отмену скрытие произойдёт само.

А ещё: диалоги принято вызывать так: retcode = dialog.exec() и проверять retcode == Accepted.

А ещё: пихтон имеет сборщик мусора. Если у тебя не пицот полей, то del [:] тебе не нужен.

// «На Фортране можно писать на любом языке...»

schizoid ★★★ ()
Ответ на: комментарий от schizoid

А где QApplication?

Без понятия: стащил код и чуть переделал его, чтобы переменное количество параметров можно было брать.

А ещё: QFormLayout тебе нужен.

Так без цикла-то формочка появляется, только фиг что из нее получишь…

Если у тебя не пицот полей, то del [:] тебе не нужен.

Я это сделал, чтобы если пользователь что-то вводил, но нажал cancel, данные не поступили в вызвавшую функцию.

Eddy_Em ☆☆☆☆☆ ()

Жутко. PyGTK выходил изящнее как-то

#!/usr/bin/python
# -*- coding: utf-8 -*-

import sys
from PyQt4 import QtGui, QtCore

appcode = -1

# Возвращает либо список значений linedit-ов, либо пустой список.
def getParameters(labels, title='Tell me more'):
    global appcode
    app = QtGui.QApplication(sys.argv)

    form = QtGui.QFormLayout()
    edits = {}
    for label in labels:
        edit = QtGui.QLineEdit() # Есть ещё QSpinBox и QDoubleSpinBox, если что.
        form.addRow(label, edit)
        edits[label] = edit

    buttons = QtGui.QDialogButtonBox()
    buttons.setOrientation(QtCore.Qt.Horizontal)
    buttons.setStandardButtons(QtGui.QDialogButtonBox.Cancel|QtGui.QDialogButtonBox.Ok)
    layout = QtGui.QVBoxLayout()
    layout.addLayout(form)
    layout.addWidget(buttons)
    
    global success
    success = False
    def ok(): 
        global success
        success = True
        w.close() 
    def cancel():
        global success
        success = False
        w.close() 
    QtCore.QObject.connect(buttons, QtCore.SIGNAL("accepted()"), ok);
    QtCore.QObject.connect(buttons, QtCore.SIGNAL("rejected()"), cancel);
    
    w = QtGui.QDialog()
    w.setWindowTitle(title)
    w.setLayout(layout)
    QtCore.QMetaObject.connectSlotsByName(w)
    w.show()
    appcode = app.exec_()
    
    if success:
        return [edits[label].text() for label in edits]
    return []
    
# Пример вызова.
if __name__ == '__main__':
    print getParameters(['One', 'Two', 'Three'])
    sys.exit(appcode) # Вот эта строка, в принципе, не обязательна, как и appcode.
schizoid ★★★ ()
Ответ на: комментарий от Eddy_Em

А
import название_файла
позволит подключить функцию getParameters? А то я ее из другого скрипта запускаю.

Конечно. Только вызывать надо module_name.getParameters().

Или можно сделать from module_name import getParameters и вызывать просто по имени. Но это, как бы, плохой стиль.

schizoid ★★★ ()
Ответ на: комментарий от Eddy_Em

Да. 'название_файла' в этом случае должно быть либо в одной директории с основным скриптом, либо лежать в ${PYTHONPATH}. Можно еще в поддиретории класть но тогда в них надо создавать файл __init__.py и использовать другую структуру импорта:

 import subdir_name.script_name
fat_angel ★★★★★ ()
Ответ на: комментарий от schizoid

можно сделать from module_name import getParameters и вызывать просто по имени. Но это, как бы, плохой стиль.

Вовсе нет, плохой стиль это: from module_name import *, и то не всегда.

buddhist ★★★★★ ()
Ответ на: комментарий от schizoid

Что-то я еще читал про

from module_name import Parameter as Parm
а потом как к Parm к нему обращаться…

Eddy_Em ☆☆☆☆☆ ()
Ответ на: комментарий от Eddy_Em

Под gtk3 его нет, если чё.

А в целом - кути хорош но именно питоновые биндинги лучше на gtk.

anonymous ()
Ответ на: комментарий от anonymous

Под gtk3 его нет

А мне под это Г и не нужно: под GTK2, естественно.

Eddy_Em ☆☆☆☆☆ ()
Ответ на: комментарий от schizoid

Вот же черт: в командной строке запускается, а freecad от этого падает:

Illegal storage access...

Eddy_Em ☆☆☆☆☆ ()
Ответ на: комментарий от Eddy_Em

Обнаружил в чем проблема: окно даже не успевает показаться, как функция getParameters возвращает пустой массив. Таки нужно как-то ждать окончания ввода.

Eddy_Em ☆☆☆☆☆ ()
Ответ на: комментарий от Eddy_Em

Какое все-таки говно этот ваш питон!

Вообще жесть, а не язык: типы переменных не определяются, в массиве может храниться свалка, от форматирования зависит логика программы…

Нет уж…

Eddy_Em ☆☆☆☆☆ ()
Ответ на: комментарий от Eddy_Em

Здесь это звучит буквально так: Взять нечто(функцию класс, другой модуль) с именем Parameter из модуля module_name и именовать дальше как Parm. Иногда полезно использовать.(например если Parameter имя другого модуля и его каждый раз надо писать... или когда уже такое имя закреплено за другим объектом)

deterok ★★★★★ ()
Ответ на: комментарий от deterok

CopyTools.py:

import FreeCAD, FreeCADGui
from NCopy import copyVec
from FreeCAD import Base

class _CopyVec:
	"Copy selected object[s] N times along vector"
	def IsActive(self):
		if len(FreeCADGui.Selection.getSelection()) > 0:
			return True
		else:
			return False

	def Activated(self):
		"Multiple copy by vector"
		from getGUIparams import getNparametersFromWindow as getWinPars  
		FreeCAD.Console.PrintMessage("CopyVec activated!\n")
		L = getWinPars(["a","b","c","d"])
		if len(L) != 4:
			return
		try:
			N = int(L[0].text())
			dx = float(L[1].text())
			dy = float(L[2].text())
			dz = float(L[3].text())
		except:
			FreeCAD.Console.PrintError("Wrong input! Only numbers allowed...\n")
		else:
			copyVec(N, Base.Vector(dx,dy,dz))

	def GetResources(self):
		IconPath = FreeCAD.ConfigGet("UserAppData")  + "Mod/CopyTools/NCopy.png"
		return {'Pixmap' : IconPath, 'MenuText': 'Copy Vec', 'ToolTip': 'Copy selected objects N times by given vector'} 
FreeCADGui.addCommand('CopyTools_CopyVec', _CopyVec())
Файл getGUIParams сейчас выглядит так (не работает все равно):
import sys
import pygtk
pygtk.require('2.0')
import gtk
#import FreeCAD, FreeCADGui

# Returns a list of strings or empty list if user cancel's
def getNparametersFromWindow(labels, title='Tell me more'):
	def callback(self, widget, data=None):
		print "Hello again - %s was pressed" % data
	def delete_event(self, widget, event, data=None):
		gtk.main_quit()
		return False
	def __init__(self):
		window = gtk.Window(gtk.WINDOW_TOPLEVEL)
		window.set_title("Table")
		window.connect("delete_event", delete_event)
		vbox = gtk.VBox(False, 5)
		window.add(vbox)
		box.show()
		for label in labels:
			box = gtk.HBox(False, 5)
			vbox.pack_start(box, True, True, 0)
			box.show()
			edit = gtk.Entry()
			glabel = gtk.Label(label)
			box.pack_start(glabel, False, False, 0)
			box2.pack_start(edit, True, True, 0)
			edits.append(edit)
		box = gtk.HBox(False, 5)
		vbox.pack_start(box, True, True, 0)
		box.show()
		button = gtk.Button("OK")
		button.connect("clicked", callback, "OK")
		box.pack_start(button, False, False, 0)
		button.show()
		button = gtk.Button("Cancel")
		button.connect("clicked", self.callback, "Cancel")
		box.pack_start(button, True, True, 0)
		button.show()
		window.show()

Eddy_Em ☆☆☆☆☆ ()
Ответ на: комментарий от Eddy_Em

С gtk не помогу, не работал с ним, я имел ввиду код с использованием qt. Или он весь и был представлен ранее?

deterok ★★★★★ ()
Ответ на: комментарий от deterok

К фрикаду документации почти нет. И как к нему прикрутить сишный функционал - непонятно.

На питоне по крайней мере есть примеры. Да и консоль у него питоновская (правда, конечно, можно выполнять из питона любой бинарь…)

Eddy_Em ☆☆☆☆☆ ()
Ответ на: комментарий от deterok

Да ладно. «Забью» на то, что не понимаю: в питоновской консоли работает - и хватит. А если уж кому GUI нужно будет - нехай сам лепит. Я и так уже чуть клавиатуру от злости не расколотил из-за этого скотского питона, кактус в задницу его создателю!

Eddy_Em ☆☆☆☆☆ ()
Ответ на: комментарий от Eddy_Em

Ну пц., почитайте ченьть по основам гуи на python+gtk.

У вас куча куча каких-то невообразимых ошибок.

C фрикадом не сталкивался и не понимаю что вам конкретно надо, типа этого чтоли

#!/usr/bin/python
# coding: utf-8
import gtk

class MyWin:
	def __init__(self, labels=None):
		window = gtk.Window(gtk.WINDOW_TOPLEVEL)
		window.set_title("Table")
		window.connect("destroy", self.delete_event)
		vbox = gtk.VBox(False, 5)
		window.add(vbox)
		self.edits = []
		for label in labels:
			box = gtk.HBox(False, 5)
			vbox.pack_start(box, True, True, 0)
			edit = gtk.Entry()
			glabel = gtk.Label(label)
			box.pack_start(glabel, False, False, 0)
			box.pack_end(edit, True, True, 0)
			self.edits.append(edit)
		box = gtk.HBox(False, 5)
		vbox.pack_start(box, True, True, 0)

		button = gtk.Button("OK")
		button.connect("clicked", self.ok)
		box.pack_start(button, False, False, 0)

		button = gtk.Button("Cancel")
		button.connect("clicked", self.no)
		box.pack_start(button, True, True, 0)

		window.show_all()


	def ok(self, widget):
		print "O.K.!"
		allvals = []
		for e in self.edits:
			value = e.get_text()
			if value:
				allvals.append(value)

 		print ', '.join(allvals)


	def no(self, widget):
		print "Cancel!"
		gtk.main_quit()


	def delete_event(self, widget):
		gtk.main_quit()


if __name__ == "__main__":
	alllab = ("label1", "label2", "label3")
	MyWin(labels=alllab)
	gtk.main()

anonymous ()
Ответ на: комментарий от anonymous

Мне из этой штуки надо вернуть параметры, введенные пользователем. А параметры используются в другом модуле. В этом-то и проблема: freecad либо сразу же закрывает окно, либо открывает его, но возвращает основной функции управление.

Eddy_Em ☆☆☆☆☆ ()
Ответ на: комментарий от anonymous

Примеры фрикадовских диалогов есть (правда, на дурацких кутях). Но там все введенные пользователем значения остаются внутри функции, а не передаются «наружу».

С механизмом работы питона я вообще не знаком, поэтому-то и не представляю, как осуществить межфункциональное взаимодействие.

Eddy_Em ☆☆☆☆☆ ()
Ответ на: комментарий от Eddy_Em

Импортируйте ваш исполняющий модуль(CopyTools.py как я понимаю?) в эту гуйню

А, пригляделся - у вас всё ровно наборот, гуйня в CopyTools импортируется.Ну это неверно имхо, хотя можно и так.

Например это типа ваш CopyTools

#!/usr/bin/python
# coding: utf-8
import getGUIParams
alllab = ("label1", "label2", "label3")
getGUIParams.runner(alllab)
print getGUIParams.allvals
вышеприведённый пример назовем как и у вас, getGUIParams, только вот небольшие изменения
--- getGUIParamsOLD.py	2012-06-15 10:49:41.935701007 +0400
+++ getGUIParams.py	2012-06-15 10:52:49.479701001 +0400
@@ -2,6 +2,8 @@
 # coding: utf-8
 import gtk
 
+allvals = []
+
 class MyWin:
 	def __init__(self, labels=None):
 		window = gtk.Window(gtk.WINDOW_TOPLEVEL)
@@ -34,13 +36,12 @@
 
 	def ok(self, widget):
 		print "O.K.!"
-		allvals = []
 		for e in self.edits:
 			value = e.get_text()
 			if value:
 				allvals.append(value)
 
- 		print ', '.join(allvals)
+		gtk.main_quit()
 
 
 	def no(self, widget):
@@ -52,9 +53,8 @@
 		gtk.main_quit()
 
 
-if __name__ == "__main__":
-	alllab = ("label1", "label2", "label3")
-	MyWin(labels=alllab)
-	gtk.main()
-
+class runner:
+	def __init__(self, alllab):
+		MyWin(labels=alllab)
+		gtk.main()
 

anonymous ()
Ответ на: комментарий от anonymous

Сделал так:

import sys
import pygtk
pygtk.require('2.0')
import gtk
#import FreeCAD, FreeCADGui

allvals = []

class MyWin:
	def __init__(self, labels, title):
		window = gtk.Window(gtk.WINDOW_TOPLEVEL)
		window.set_title(title)
		window.connect("destroy", self.delete_event)
		vbox = gtk.VBox(False, 5)
		window.add(vbox)
		self.edits = []
		for label in labels:
			box = gtk.HBox(False, 5)
			vbox.pack_start(box, True, True, 0)
			edit = gtk.Entry()
			glabel = gtk.Label(label)
			box.pack_start(glabel, False, False, 0)
			box.pack_end(edit, True, True, 0)
			self.edits.append(edit)
		box = gtk.HBox(False, 5)
		vbox.pack_start(box, True, True, 0)
		button = gtk.Button("OK")
		button.connect("clicked", self.ok)
		box.pack_start(button, False, False, 0)
		button = gtk.Button("Cancel")
		button.connect("clicked", self.no)
		box.pack_start(button, True, True, 0)
		window.show_all()
	def ok(self, widget):
		print "O.K.!"
		global allvals
		for e in self.edits:
			value = e.get_text()
			if value:
				allvals.append(value)
 		gtk.main_quit()
	def no(self, widget):
		print "Cancel!"
		gtk.main_quit()
	def delete_event(self, widget):
		gtk.main_quit()

class runner:
	def __init__(self, alllab, atitle='Title'):
		MyWin(labels=alllab, title=atitle)
		gtk.main()

#~ def getNparametersFromWindow(labels, title='Title'):
	#~ MyWin(labels, title)
	#~ gtk.main()
Вызваю так:
		from getGUIparams import runner as getWinPars
		from getGUIparams import allvals as L
		FreeCAD.Console.PrintMessage("CopyVec activated!\n")
		getWinPars(["a","b","c","d"])
		is_array = lambda var: isinstance(var, (list, tuple))
		if (is_array(L) and len(L) != 4):
			return
		try:
			N = int(L[0].text())
			dx = float(L[1].text())
			dy = float(L[2].text())
			dz = float(L[3].text())
		except:
			FreeCAD.Console.PrintError("Wrong input! Only numbers allowed...\n")
		else:
			copyVec(N, Base.Vector(dx,dy,dz))
Фигвам. Не работает. И при нажатии на «кнопки» в первый раз окно все равно не закрывается, а при втором нажатии фрикад падает.

Eddy_Em ☆☆☆☆☆ ()
Ответ на: комментарий от Eddy_Em

жесть, а не язык

с таким подходом ничего не получится у вас. :) Настройтесь на позитив и читайте маны.

Bad_ptr ★★★★ ()
Ответ на: комментарий от Eddy_Em

Какое все-таки говно этот ваш питон!

Создатели brainworkshop должны быть, по логике, умными ребятами, но он написан на питоне. Хм..

madcore ★★★★★ ()
Ответ на: комментарий от Eddy_Em

форматирования зависит логика программы…

это не баг, а фича.

thunar ★★★★★ ()
Ответ на: комментарий от thunar

Да ужас же: скопипастишь код, где отступы пробелами; сделаешь отступы табами (у меня везде так) - фигвам.

Нет switch'а - это жесть!
Классы… Нафиг?
Нет типов данных.
Нет указателей в явном виде.

В общем, дрянной язык.

Eddy_Em ☆☆☆☆☆ ()
Ответ на: комментарий от Eddy_Em

Нет switch'а - это жесть!

хуже того... GOTO НЕТУ!!!! 11111111111;-)

А чего, Tkinetr не подойдет? А то у меня под него есть феня для создания форточек с параметрами.

AIv ★★★★★ ()
Ответ на: комментарий от AIv

GOTO НЕТУ!

Это тоже косяк. Во многих случаях goto очень даже нужен.

А чего, Tkinetr не подойдет?

Не знаю: я вообще с питоном второй день знаком ☺

Eddy_Em ☆☆☆☆☆ ()
Ответ на: комментарий от Eddy_Em

В общем, дрянной язык.

ну и брось ты его. я вот, например, совершенно не знаю ни питона, ни перла, и нахожу, что на перле писать значительно приятнее, когда припрет.

а для расширения приложений надо использовать только тикль, и это не обсуждается. ну в крайнем случае лисп. но лучше все-таки тикль.

anonymous ()
Ответ на: комментарий от Eddy_Em

Это тоже косяк. Во многих случаях goto очень даже нужен.

А зачем было из криокамеры вылезать тогда? Замерзли?;-)

AIv ★★★★★ ()
Ответ на: комментарий от Eddy_Em

Нет switch'а - это жесть!

Косяк конечно, но if'ов обычно хватает.

Классы… Нафиг?

Не осилившим ООП, разрешаю классами не пользоваться.

Нет типов данных.

Все там есть — это тебе не баш, man утиная типизация.

Нет указателей в явном виде.

Указатели в скриптовом языке? Да ты в конец упоролся!

fat_angel ★★★★★ ()
Ответ на: комментарий от Eddy_Em

Во многих случаях goto очень даже нужен.

Пример можно?

fat_angel ★★★★★ ()

python, негодую

фигасе ты велосипедостроитель, да ещё и фердыщенкопоследователь

shty ★★★★★ ()
Ответ на: комментарий от shty

фердыщенкопоследователь

Для тех кто в танке, щито это?

fat_angel ★★★★★ ()
Ответ на: комментарий от Eddy_Em

Какое все-таки говно этот ваш питон!

лучше руки распрями вместо матюканий

shty ★★★★★ ()
Ответ на: комментарий от Eddy_Em

Я и так уже чуть клавиатуру от злости не расколотил из-за своей тупости, кактус в задницу мне за то что плохо учился в институте!

// поправил

shty ★★★★★ ()
Ответ на: комментарий от Eddy_Em

Да ужас же: скопипастишь код

и правда - ужас

такие вот как ты «умельцы» тот FreakAD писали и теперь ты злишься, а надо бы задуматься :)

shty ★★★★★ ()
Ответ на: комментарий от Eddy_Em

Нет switch'а - это жесть!

есть, и это не жесть в любом разе

Классы… Нафиг?

ну есть же, ну

Нет типов данных.

есть, не пясди

Нет указателей в явном виде.

они тебе не нужны здесь

shty ★★★★★ ()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.