使用拖放进行 Python GUI 编程,还包含标准输出重定向
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/17698138/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Python GUI programming using drag and drop, also incorporating stdout redirect
提问by Clinton Moffat
I'm new to programming & new to python. I've just developed my first script, it prosesses file, but at the moment only from the commandline.
我是编程新手和 python 新手。我刚刚开发了我的第一个脚本,它处理文件,但目前只能从命令行。
This is just a hobby to me so my job does not depend on it :-)
这对我来说只是一种爱好,所以我的工作不依赖于它:-)
I've spent a few days now trying to get my head around python gui development & have come to the conclusion that I must be stupid.
我现在花了几天时间试图了解 python gui 开发,并得出结论,我一定是愚蠢的。
I've looked at wxpython & Tkinter & do not understand either, although Tkinter seems to be the easier out of the two. I've even looked at wysiwyg tools like Boa Contrictor & wxglade. I do not even understand how to use those. I would prefer to just stick with my editor & code manually anyway.
我看过 wxpython & Tkinter & 也不明白,尽管 Tkinter 似乎是两者中更容易的。我什至看过像 Boa Contrictor & wxglade 这样的所见即所得的工具。我什至不明白如何使用这些。无论如何,我宁愿坚持使用我的编辑器和代码。
My problem is this:
我的问题是这样的:
I would like to create a desktop window with either 1 or two objects, depending on what works best. If just one object then a text box of some sort, if 2 objects then a text box & an image.
我想创建一个包含 1 个或两个对象的桌面窗口,具体取决于哪种效果最好。如果只有一个对象,则是某种文本框,如果有 2 个对象,则是文本框和图像。
I want to be able to drag file from a file manager & drop them on my script window, this is just to pass the filenames to my script.
我希望能够从文件管理器中拖动文件并将它们放在我的脚本窗口中,这只是将文件名传递给我的脚本。
I than want to redirect stdout to an object within my desktop window so that all script output appears within the desktop window.
我不想将标准输出重定向到桌面窗口中的一个对象,以便所有脚本输出都出现在桌面窗口中。
I'm not sure if one object can do both things or not. If it can than just a text box would suffice, else drop files onto image & have redirected output going to the text box.
我不确定一个对象是否可以同时做两件事。如果它不仅仅是一个文本框就足够了,否则将文件拖放到图像上并将输出重定向到文本框。
I have found drag & drop examples on the web but nothing which incorporates stdout redirect, & I've not been able to successfully modify any of the examples that I've come across.
我在网上找到了拖放示例,但没有任何包含标准输出重定向的示例,并且我无法成功修改我遇到的任何示例。
If somee kind sole has the time to demonstrate how to achieve what I want & explain how its works I would greatfully appreciate it!
如果有人有时间来演示如何实现我想要的并解释它的工作原理,我将不胜感激!
----EDIT ----
- - 编辑 - -
I've been playing around with 2 examples & have managed to hash the 2 together in order to get what I wanted working. Code is below. It's not cleaned up yet ( old comments etc... ), but it works.
我一直在玩 2 个例子,并设法将 2 个散列在一起,以获得我想要的工作。代码如下。它尚未清理(旧评论等...),但它有效。
#!/usr/bin/python
# The next two lines are not necessary if you installed TkDnd
# in a proper place.
import os
from Tkinter import *
os.environ['TKDND_LIBRARY'] = '/home/clinton/Python/tkdnd2.6/'
import Tkinter
from untested_tkdnd_wrapper import TkDND
class Redir(object):
# This is what we're using for the redirect, it needs a text box
def __init__(self, textbox):
self.textbox = textbox
self.textbox.config(state=NORMAL)
self.fileno = sys.stdout.fileno
def write(self, message):
# When you set this up as redirect it needs a write method as the
# stdin/out will be looking to write to somewhere!
self.textbox.insert(END, str(message))
root = Tkinter.Tk()
dnd = TkDND(root)
textbox = Tkinter.Text()
textbox.pack()
def handle(event):
event.widget.insert(END, event.data)
content = textbox.get("0.0",Tkinter.END)
filename = content.split()
dnd.bindtarget(textbox, handle, 'text/uri-list')
#Set up the redirect
stdre = Redir(textbox)
# Redirect stdout, stdout is where the standard messages are ouput
sys.stdout = stdre
# Redirect stderr, stderr is where the errors are printed too!
sys.stderr = stdre
# Print hello so we can see the redirect is working!
print "hello"
# Start the application mainloop
root.mainloop()
Examples are: python drag and drop explorer files to tkinter entry widget
示例是:python 将资源管理器文件拖放到 tkinter 条目小部件
And also the example provided kindly by Noelkd.
还有 Noelkd 提供的例子。
In order for this code to work you must create the wrapper from first example. Also currently code just displays dragged file in window, however variable is in place to be passed onto the script which runs behind the gui interface.
为了使此代码工作,您必须从第一个示例创建包装器。此外,当前代码仅在窗口中显示拖动的文件,但是变量已准备好传递到在 gui 界面后面运行的脚本上。
回答by Paco
Have a look at GTK. It is a really powerful library. Not the simplest, that's a fact, but once you get to understand how things work, it becomes much easier. Here's the official tutorial
看看GTK。这是一个非常强大的库。不是最简单的,这是事实,但是一旦您了解事情的工作原理,它就会变得容易得多。这是官方教程
If oyu are still using Python2, I think you should use PyGTKbut it has been replaced by gl (which is described in the above tutorial). A good tutorial for PyGTK can be found here.
如果oyu仍在使用Python2,我认为您应该使用PyGTK,但它已被gl(在上面的教程中描述)所取代。可以在此处找到有关 PyGTK 的好教程。
For a static interface, you can use gladewhich produces XML files that are then read by GTKBuilder to create the "real" interface. The first tutorial that I've found is available here
对于静态接口,您可以使用空地产生,然后由GTKBuilder阅读创造的“真正的”接口的XML文件。我找到的第一个教程可以在这里找到
回答by Noelkd
If you want to use Tkinter:
如果你想使用 Tkinter:
from Tkinter import *
import tkFileDialog
class Redir(object):
# This is what we're using for the redirect, it needs a text box
def __init__(self, textbox):
self.textbox = textbox
self.textbox.config(state=NORMAL)
self.fileno = sys.stdout.fileno
def write(self, message):
# When you set this up as redirect it needs a write method as the
# stdin/out will be looking to write to somewhere!
self.textbox.insert(END, str(message))
def askopenfilename():
""" Prints the selected files name """
# get filename, this is the bit that opens up the dialog box this will
# return a string of the file name you have clicked on.
filename = tkFileDialog.askopenfilename()
if filename:
# Will print the file name to the text box
print filename
if __name__ == '__main__':
# Make the root window
root = Tk()
# Make a button to get the file name
# The method the button executes is the askopenfilename from above
# You don't use askopenfilename() because you only want to bind the button
# to the function, then the button calls the function.
button = Button(root, text='GetFileName', command=askopenfilename)
# this puts the button at the top in the middle
button.grid(row=1, column=1)
# Make a scroll bar so we can follow the text if it goes off a single box
scrollbar = Scrollbar(root, orient=VERTICAL)
# This puts the scrollbar on the right handside
scrollbar.grid(row=2, column=3, sticky=N+S+E)
# Make a text box to hold the text
textbox = Text(root,font=("Helvetica",8),state=DISABLED, yscrollcommand=scrollbar.set, wrap=WORD)
# This puts the text box on the left hand side
textbox.grid(row=2, column=0, columnspan=3, sticky=N+S+W+E)
# Configure the scroll bar to stroll with the text box!
scrollbar.config(command=textbox.yview)
#Set up the redirect
stdre = Redir(textbox)
# Redirect stdout, stdout is where the standard messages are ouput
sys.stdout = stdre
# Redirect stderr, stderr is where the errors are printed too!
sys.stderr = stdre
# Print hello so we can see the redirect is working!
print "hello"
# Start the application mainloop
root.mainloop()
What this does is creates a window with a button and a text box, with stdout redirect.
这样做是创建一个带有按钮和文本框的窗口,并带有标准输出重定向。
Currently in Tkinter you can't drag and drop files on to the open tk window(you can if you use tkdnd), so I have included a different way of getting the path of a file.
目前在 Tkinter 中,您无法将文件拖放到打开的 tk 窗口(如果您使用tkdnd,则可以),因此我提供了一种获取文件路径的不同方法。
The way I have included to select a file is the askopenfilename dialog from tkFileDialog, this opens up a file browser and the path file selected is returned as a string.
我选择文件的方式是 tkFileDialog 中的 askopenfilename 对话框,这会打开一个文件浏览器,所选的路径文件以字符串形式返回。
If you have any questions or this doesn't quite do what your looking for please leave a comment!
如果您有任何问题或这不完全符合您的要求,请发表评论!