I built a password-generator with python. It runs fine in the IDLE but whenever I convert the .py file to an .exe, it closes immediately on a machine with no python installed.
So I wanted to build it a GUI, to prevent the closing.
I want to display the generated password, which is saved in a variable, in a Text-Edit widget.
This is a part of the method which stores it.
# Conversion of list to string
stringpw = ""
for i in lst:
stringpw = stringpw + str(i)
# change positions
def change_text(stringpw):
total= []
for wort in stringpw.split():
w = list(wort)
random.shuffle(w)
total.append("".join(w))
return " ".join(insgesamt)
finalPassword = change_text(stringpw)
return finalPassword
I translated it to english, because it's coded in another language, just in case there are mistakes in the code. However the original code runs fine without any problem.
My problem is, that it doesn't show the finalPassword in the Text-Edit widget, when I run this (the output field exists and the self.ui referring to it is instantiated earlier):
self.ui.output.setPlainText(finalPassword)
Is there a possibility to display this variable? Cause normally you can only show a string in the brackets.
Did you use QPlainTextEdit to print the password or lineEdit?
if QPlainTextEdit then you should use appendPlainText insted of setPlainText
Related
Hello
I do not know what to do, the window (register.py) opens very well from login.py, but the window (login.py) does not not open since register.py.
What to do?
register.py
https://hastebin.com/oyoxoyemak.rb
login.py
https://hastebin.com/tanuhigome.rb
error code
error code if i remove
screen = app.primaryScreen()
size = screen.size()
print('Size: %d x %d' % (size.width(), size.height()))
rect = screen.availableGeometry()
print('Available: %d x %d' % (rect.width(), rect.height()))
self.window.move((rect.width() / 2) - 230, (rect.height() / 2) - 230)
error code 2
Both issues are related to the scope.
app is a local variable in both scripts, which exists only in the scope of the script that is running (the if __name__ == "__main__": line).
So, if you run login.py, app is available in its scope, but if you run register.py app exists only for it, but not in the login.py scope (since it was never created "there").
Since primaryScreen is a static function, you don't need a reference to the application instance (which you could get through QtWidgets.QApplication.instance(), anyway):
Just change that line to:
screen = QtWidgets.QApplication.primaryScreen()
In the second issue, the problem is similar: since you're running login.py, MainWindow_Register is never declared in register.py.
I have not a "simple" solution for that, as your approach is a bit confused.
First of all, it seems like you're trying to implent your program starting from the output of pyuic, and if that's the case you should really avoid it: write your own code and use the pyuic generated files as suggested in the documentation.
Then, whenever you have to face multiple related windows, it's better to avoid calling themselves "recursively", and use a single window (or better, a separate object, even a subclass of QApplication) as a "manager". This will make everything easier programmatically, avoiding redundant code, while decreasing the possibility of bugs.
In your case, you should probably always use the login window as a "starting point", then show the register one whenever necessary.
I am looking for a solution to add a function to a program using Python. I want to copy and paste selected data (selected with the mouse).
Example:
Copy "Hello" using CTRL-C from the sentence "Hello everybody" when I select Hello.
Copy a part of array selected using CTRL-C
My main problem is how to use the selected data. But now I just can copy string defined in the code (here "tt"):
clipboard.OpenClipboard()
clipboard.EmptyClipboard()
clipboard.SetClipboardText('tt')
clipboard.CloseClipboard()
I tried several codes found on the internet and in this website but none of them fixed my problem.
You don't need to call clipboard.SetClipboardText(). When a program supports the clipboard, then Ctrl+C will copy the currently selected text into the clipboard. There is nothing you need to do to make this happen.
If your question is "How can I trigger Ctrl+C from outside of a program to copy the currently selected text into the clipboard", then the answer is: Usually, you can't. For security reasons, most programs don't respond to artificial key events which other programs send them.
The second error is something else entirely. Your class CopyEvent doesn't have a property list, so Python can't invoke methods in it.
The final code if someone is interested:
from eventbase import EventBase
import win32clipboard as clipboard
import os
import wx
class CopyEvent(EventBase):
TYPE = wx.NewEventType()
ID = wx.NewId()
BINDER = wx.PyEventBinder(TYPE, 1)
SHORTCUT_MODIFIER = wx.ACCEL_CTRL
SHORTCUT_KEY = ord('C')
def __init__(self, variable=None):
EventBase.__init__(self)
self._variable = variable
def execute(self, viewmodel, parent):
clipboard.OpenClipboard()
clipboard.EmptyClipboard()
text = self._convert_variable_to_text(self._variable)
clipboard.SetClipboardText(text)
clipboard.CloseClipboard()
self.logger.info("Copying variable to clipboard")
def _convert_variable_to_text(self, variable) :
lines = []
lines.append("\t".join(variable.column_names))
for row_nbr in variable.row_numbers:
lines.append("\t".join([repr(i) for i in variable.get_row_as_tuple(row_nbr)]))
return os.linesep.join(lines)
Question
Is there any way to automate a tkFileDialog selection to run it through unittest? The following is the only use of tkinter in my application:
root = Tkinter.Tk()
types = [('Comma Separated Values', '.csv'), ('All Files', '*')]
filename = tkFileDialog.askopenfilename(parent=root,
filetypes=types)
root.destroy()
Edit: I didn't mention that this part of the code was trapped in a method call from a class outside my control.
Background
I've built a local app that creates an http server on localhost and runs its GUI with HTML/CSS/JS in a web browser. Because of browser restrictions, I can't use the built-in file dialog and so have to send this request through Python. I want this to run on a OSX with the built-in Python 2.5. I'm not very familiar with Tcl/Tk.
Attempt #1
If I could get to the underlying widgets, I could generate the clicks like in this question. However, looking at the dialog source, it appears to me that the Tcl call in lines 48-50 is blocking. Is this a correct assumption?
Attempt #2
I thought there might be a way using Tcl commands directly through root.tk.call. Since I'm on Python2, I think the underlying Tcl is a single call to tk_getOpenFile. Would I have to ensure the Tcl interpreter is threaded? Is there any Tcl/Tk command that can help me out here?
Attempt #3
I could implement the file selection from scratch using os.listdir etc. (Probably in a separate HTML page communicating back and forth with the server). It would be more than a little painful and hopefully avoidable.
Solution
Based on A. Rodas's answer below, I came up with the following:
import tkFileDialog
old_dialog = tkFileDialog.askopenfilename
try:
tkFileDialog.askopenfilename = lambda *args, **kw: filename
# First test dialog cancelled
filename = ''
method_that_calls_tk()
# run some assertions
# Next test a valid file name with valid contents
filename = self.VALID_FILENAME
method_that_calls_tk()
# run some assertions
# Now test a valid file name with invalid contents
filename = self.INVALID_CONTENTS_FILENAME
method_that_calls_tk()
# run some assertions
# Now test an invalid file name
filename = self.INVALID_FILENAME
method_that_calls_tk()
# run some assertions
finally:
tkFileDialog.askopenfilename = old_dialog
Unit testing of Tkinter code is not an easy issue. For instance, the IDLE does not have a proper test suite, even though it is part of the standard library. Since you mention that this is going to be the only use of Tkinter in your application, I'd suggest to make unit tests for the outcome of this code: the value of filename.
For instance, you can have a test for a .csv file, and another one for an incorrect file extension. Since tkFileDialog returns an empty string if it is closed by the user, add also a test where filename = ''.
import unittest
class TestFileDialog(unittest.TestCase):
def test_dialog_closed(self):
filename = ''
# ...
def test_incorrect_extension(self):
filename = '/path/to/another/filetype'
# ...
def test_csv_extension(self):
filename = '/path/to/correct/file.csv'
# ...
You could just patch the calls to tkinter:
patch tk.Tk() because most CI's will error because they don't have displays.
Also patch the file dialog so you can simulate return values and that it is being called with what you expect.
#patch('your_module.tk.Tk')
def test_your_stuff(self, Tk)
with #patch('your_module.tkFileDialog.askopenfilename') as file_dialog:
expected = 'expected return value'
assert expected = your_function_calling_file_dialog()
file_dialog.assert_called_once_with(whatever, you, expect, it, to, be, called, with)
I am trying to write a procedure that will automate the procedure of making a tkinter window, so I am trying to use the open() function to open a txt file (probably should be a .py shouldn't it?) that a procedure that makes the window, the code I am trying to have it write is:
def a_procedure():
window = Tk()
#rest of code necessary to make a Tkinter window
but the problem is, when I use
open()
textfile.write("def a_procedure()"/
"window = Tk()")
what I get in the text file is: def a_procedure(): window = TK() #rest of text
Is there (a)A way to write multiple lines with
open()
or (b)A better way to write a procedure with a procedure
Your example doesn't show how you're going to vary the generated function (since if they're all the same you don't need to generate them). So I'll show a different example where a function can return a new function.
def make_function(first_multiplicand):
def multiply(second_multiplicand):
return first_multiplicand * second_multiplicand
return multiply
Then you can make functions that multiply by different amounts:
doubler = make_function(2)
tripler = make_function(3)
print doubler(7), tripler(7)
This way you don't have to write out a .py file and then import it (which has potential problems if you can't write out files anywhere helpful, as well as requiring you to create Python source code by string formatting, which is pretty ugly).
It's also worth looking at functools, particularly functools.partial; you could rewrite the above using it as follows:
import functools
def make_function(first_multiplicand):
def multiply(first, second):
return first * second
return functools.partial(multiply, first_multiplicand)
You can use multi-line strings:
textfile.write("""
def a_procedure():
window = Tk()
""")
Just make sure to keep stuff indented properly.
Why do you need to generate Python from a Python script?
Try: "def a_procedure():\n\twindow = Tk()"
I was writing a little program that takes a list and generates a menu out of it in curses (straight up, standard library or whatever, batteries included python's curses) when I noticed the strangest problem (if you'd like, a heavily commented copy of the entire program is below). Simply put, when accepting the results of an os.listdir generated list, curses crashes with an addstr ERR, BUT, if I feed it a hardcoded list, it works fine. This, of course, makes absolutely no sense, right? A list is a list is a list and a list by any other name should still be a list, right?
To make things even more complicated, I sent the code to a friend of mine who works mainly in python2.6 (mine was originally written to work in python3.1). He uncommented the broken_input() call (which feeds the program the os.listdir generated information) and said that it worked fine for him. I have both python 2.6 and 3.1 installed, so I changed my shebang to make the program run in 2.6, and (with the broken_input() uncommented) for me, it still throws the addstr ERR (yet runs fine with the hardcoded input... which is, of course, btw, entirely useless apart from proof of concept).
Thus, my question is this: is there something broken in my python installation (I'm running Ubuntu lucid, with python2.6.5 and 3.1 installed), and, if so, how do I fix it so I can get curses to execute this code properly. And, if it's not my python installation, how can I get the same functionality out of curses (i.e.: paint a menu from a list containing an arbitrary number of items, numbering them so that the user can make a selection based on the item number).
#!/usr/bin/env python3.1
"""curses_mp3eater.py: a curses-based implementation of my mp3eater program;
diplays the contents of cwd, allows user to make a selection. But I'm having
problems getting it to iterate over a list.
v0.1 03.14.11
by skookie sprite
address#gmail.com
"""
import curses, curses.wrapper, os, sys
def working_input():
"""the following is demo code to demonstrate my problem... main will accept the following,
but won't accept the product of a directorylist for reasons that I can't figure out."""
dircontents=['this','is','a','list','','and','it','will','iterate','fine','in','the','(main) function.']
return dircontents
def broken_input():
"""this is the code that I NEED to have work... but for reasons beyond me will not iterate in
the main function. It's a simple list of the contents of the CWD."""
cwd=os.getcwd()
dircontents=[]
for item in os.listdir(cwd):
dircontents += [item]
return dircontents
def main(stdscr):
"""This is the program. Designed to take a list of stuff and display it. If I can solve
that hurdle, I'll add selection mechanisms, and break it across screens - amongst other
things. But, currently, it can only accept the demo code. Uncomment one or the other to
see what I mean."""
#broken_input returns an addstr() ERR, but I don't see the difference between working_input
#and broken_input as they are both just lists.
#working_input() is demo code that illustrates my problem
stuffin=working_input()
#stuffin=broken_input()
#the rest of this stuff works. The problem is with the input. Why?
linenumber=int()
linenumber=6
itemnumber=int()
itemnumber=1
stdscr.clear()
stdscr.border(0)
for item in stuffin:
stdscr.addstr(linenumber, 10, '%s - %s' % (itemnumber, item), curses.A_NORMAL)
linenumber += 1
itemnumber += 1
curses.doupdate()
stdscr.getch()
if __name__ == '__main__':
curses.wrapper(main)
You're stuffing too much onto the screen and thus passing an out-of-bounds line number to addstr. If you make an empty directory to run the program in (or enlarge your terminal window), it works.
To fix this, check the number of lines in the window before the output loop in main.
use screen.scrollok(1) after addstr to allow the text to scroll.
The problem is explained in the addch manual page:
The addch, waddch, mvaddch and mvwaddch routines put the character ch
into the given window at its current window position, which is then
advanced. They are analogous to putchar(3) in stdio(3). If the
advance is at the right margin:
The cursor automatically wraps to the beginning of the next line.
At the bottom of the current scrolling region, and if scrollok is
enabled, the scrolling region is scrolled up one line.
If scrollok is not enabled, writing a character at the lower right
margin succeeds. However, an error is returned because it is not
possible to wrap to a new line
The given program neither catches an error from the lower right margin (probably should say "corner"), nor calls scrollok to allow the data to scroll up. In the latter case, you will lose information which is scrolled up, while handling the exception would allow you to prompt after a screen's worth of data is displayed, and then either quit or display more data.