I am using PyQt4 for creating a custom browser using QtWebKit, but I am stuck on saving bookmarks from the browser. Does anyone know how to achieve that?
You're a little vague on how you want this done, so I'll say we wanted to use a button imported from a UI file called bookmarks_Btn. You'll need to use the pickle module.
Here's the example code...
from PyQt4 import QtCore, QtGui, QtWebKit, uic
import pickle
class window(QtGui.QWidget):
def __init__(self, parent=None):
super(httpWidget, self).__init__(parent)
self.ui = uic.loadUi('mybrowser.ui')
self.ui.setupUi(self)
def bookmarksLoad(self):
print 'Loading bookmarks'
try:
bookOpen = open('bookmarks.txt', 'rb')
bookmarks = pickle.load(bookOpen)
bookOpen.close()
print bookmarks # Not necessary, but for example purposes
# Here you decide how "bookmarks" variable is displayed.
except:
bookOpen = open('bookmarks.txt', 'wb')
bookmarks = 'http://www.stackoverflow.com'
bookWrite = pickle.dump(bookmarks, bookOpen)
bookOpen.close()
print bookmarks # Not necessary, but for example purposes
# Here you decide how "bookmarks" variable is displayed.
QtCore.QObject.connect(self.ui.bookmarks_Btn, QtCore.SIGNAL('clicked()'), self.bookmarksLoad)
self.ui.show()
def bookmarks():
url = input 'Enter a URL: '
bookOpen = open('bookmarks.txt', 'wb')
bookOpen.write(url)
bookOpen.close()
print 'Website bookmarked!'
if __name__ == '__main__':
app = QtGui.QApplication(sys.argv)
run = window()
bookmarks()
sys.exit(app.exec_())
# You add on here, for example, deleting bookmarks.
However, if you wanted it to be retrieved from an address bar (named address, make the following changes...
# In the bookmarks function...
global url # Add at beginning
# Remove the input line.
# Add at end of __init__ in window class:
url = self.ui.address.text()
global url
That's pretty much the basics. Please note I normally program in Python 3 and PyQt5 so if there are any errors let me know :)
Related
What im trying to do is that whenever cursor is on label it must show the time elapsed since when it is created it does well by subtracting (def on_enter(i)) the value but i want it to be ticking while cursor is still on label.
I tried using after function as newbie i do not understand it well to use on dynamic labels.
any help will be appreciated thx
code:
from Tkinter import *
import datetime
date = datetime.datetime
now = date.now()
master=Tk()
list_label=[]
k=[]
time_var=[]
result=[]
names=[]
def delete(i):
k[i]=max(k)+1
time_var[i]='<deleted>'
list_label[i].pack_forget()
def create():#new func
i=k.index(max(k))
for j in range(i+1,len(k)):
if k[j]==0:
list_label[j].pack_forget()
list_label[i].pack(anchor='w')
time_var[i]=time_now()
for j in range(i+1,len(k)):
if k[j]==0:
list_label[j].pack(anchor='w')
k[i]=0
###########################
def on_enter(i):
list_label[i].configure(text=time_now()-time_var[i])
def on_leave(i):
list_label[i].configure(text=names[i])
def time_now():
now = date.now()
return date(now.year,now.month,now.day,now.hour,now.minute,now.second)
############################
for i in range(11):
lb=Label(text=str(i),anchor=W)
list_label.append(lb)
lb.pack(anchor='w')
lb.bind("<Button-3>",lambda event,i=i:delete(i))
k.append(0)
names.append(str(i))
lb.bind("<Enter>",lambda event,i=i: on_enter(i))
lb.bind("<Leave>",lambda event,i=i: on_leave(i))
time_var.append(time_now())
master.bind("<Control-Key-z>",lambda event: create())
mainloop()
You would use after like this:
###########################
def on_enter(i):
list_label[i].configure(text=time_now()-time_var[i])
list_label[i].timer = list_label[i].after(1000, on_enter, i)
def on_leave(i):
list_label[i].configure(text=names[i])
list_label[i].after_cancel(list_label[i].timer)
However, your approach here is all wrong. You currently have some functions and a list of data. What you should do is make a single object that contains the functions and data together and make a list of those. That way you can write your code for a single Label and just duplicate that. It makes your code a lot simpler partly because you no longer need to keep track of "i". Like this:
import Tkinter as tk
from datetime import datetime
def time_now():
now = datetime.now()
return datetime(now.year,now.month,now.day,now.hour,now.minute,now.second)
class Kiran(tk.Label):
"""A new type of Label that shows the time since creation when the mouse hovers"""
hidden = []
def __init__(self, master=None, **kwargs):
tk.Label.__init__(self, master, **kwargs)
self.name = self['text']
self.time_var = time_now()
self.bind("<Enter>", self.on_enter)
self.bind("<Leave>", self.on_leave)
self.bind("<Button-3>", self.hide)
def on_enter(self, event=None):
self.configure(text=time_now()-self.time_var)
self.timer = self.after(1000, self.on_enter)
def on_leave(self, event=None):
self.after_cancel(self.timer) # cancel the timer
self.configure(text=self.name)
def hide(self, event=None):
self.pack_forget()
self.hidden.append(self) # add this instance to the list of hidden instances
def show(self):
self.time_var = time_now() # reset time
self.pack(anchor='w')
def undo(event=None):
'''if there's any hidden Labels, show one'''
if Kiran.hidden:
Kiran.hidden.pop().show()
def main():
root = tk.Tk()
root.geometry('200x200')
for i in range(11):
lb=Kiran(text=i)
lb.pack(anchor='w')
root.bind("<Control-Key-z>",undo)
root.mainloop()
if __name__ == '__main__':
main()
More notes:
Don't use lambda unless you are forced to; it's known to cause bugs.
Don't use wildcard imports (from module import *), they cause bugs and are against PEP8.
Put everything in functions.
Use long, descriptive names. Single letter names just waste time. Think of names as tiny comments.
Add a lot more comments to your code so that other people don't have to guess what the code is supposed to do.
Try a more beginner oriented forum for questions like this, like learnpython.reddit.com
I have a list of buttons which is shown to the user according to a particular number which the user enters.For e.g. If the user enters 2 then only 2 buttons will be shown.
The code that does this is here:
def set(self):
global seismicAttributeCount,lineEditlist
seismicAttributeCount=int(self.ui.lineEdit_23.text())
mygroupbox = QtGui.QGroupBox()
myform = QtGui.QFormLayout()
labellist = []
buttonList= []
for i in range(seismicAttributeCount):
lineEditlist.append(QtGui.QLineEdit())
buttonList.append(QtGui.QPushButton('Browse Attribute %i'%(i+1)))
myform.addRow(lineEditlist[i],buttonList[i])
mygroupbox.setLayout(myform)
self.ui.scrollArea_12.setWidget(mygroupbox)
self.ui.scrollArea_12.setWidgetResizable(True)
for i in range(seismicAttributeCount):
if buttonList[i].clicked.connect():
print i
I want to get the index of the button clicked. Any help would be appreciated.
You probably want to look into functools.partial. This allows you to connect an event with a method and a particular input. I've made here a minimal example of a GUI that does what you want
from PyQt4 import QtGui, QtCore
import sys
import functools
class test(QtGui.QWidget):
def __init__(self,parent=None):
self.widget=QtGui.QWidget.__init__(self, parent)
# Button to add buttons
self.btnAdd = QtGui.QPushButton('Add')
self.btnAdd.connect(self.btnAdd, QtCore.SIGNAL('clicked()'), self.btnAddPressed)
# Line edit for number of buttons
self.qleN = QtGui.QLineEdit(str(0))
# List to keep track of buttons
self.buttons=[]
# Layout
self.hbox = QtGui.QHBoxLayout()
self.hbox.addWidget(self.btnAdd)
self.hbox.addWidget(self.qleN)
self.setLayout(self.hbox)
self.show()
def btnAddPressed(self):
"""Adds number of buttons."""
# Get number of buttons to add
n=int(self.qleN.text())
self.buttons=[]
for i in range(n):
# Create new button
newBtn = QtGui.QPushButton(str(i))
self.buttons.append(newBtn)
# Connect
newBtn.clicked.connect(functools.partial(self.btnPressed,i))
self.hbox.addWidget(newBtn)
def btnPressed(self,idx):
"""Returns idx of btn."""
print idx
return idx
def main():
#Creating application
app = QtGui.QApplication(sys.argv)
main_win = test()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
Note how I connect the button with a functools call and the index of the button.
By the way, next time, please make the effort and format your question properly.
Hy guys,
in my executable program there is a toolbar. Well, the user decides to move the toolbar. Now the toolbar is floating. I know I have to conntect the floating-signals that is emittted when the toolbar ist arranged by the user. How can I save the new position of the toolbar? I know the method of adding the toolbar to the main window with a position:self.addToolBar( Qt.LeftToolBarArea , toolbar_name). In the handle_floating()-method you see what I want: There I want to get the position currently, but how? You also see I have just added one member variable, named self.toolbar_pos, to hold the position of the toolbar. My idea is, when application is terminated I want to serialize this value to a file, and later, when application is ran again its will read that file and set the toolbar accordingly. But this is no problem. Currently I don't have no idea to get the position of the toolbar.
I need your help :)
#!/usr/bin/python
# -*- coding: utf-8 -*-
import sys
from PyQt4 import QtGui, QtCore
class Example(QtGui.QMainWindow):
def __init__(self, parent=None):
QtGui.QMainWindow.__init__(self, parent)
self.toolbar_pos = None
self.initUI()
def initUI(self):
exitAction = QtGui.QAction(QtGui.QIcon('exit24.png'), 'Exit', self)
exitAction.setShortcut('Ctrl+Q')
exitAction.triggered.connect(QtGui.qApp.quit)
self.toolbar = QtGui.QToolBar(self)
self.toolbar.setToolButtonStyle(QtCore.Qt.ToolButtonTextBesideIcon)
self.addToolBar(self.toolbar )
self.toolbar.addAction(exitAction)
self.toolbar.setAllowedAreas(QtCore.Qt.TopToolBarArea
| QtCore.Qt.BottomToolBarArea
| QtCore.Qt.LeftToolBarArea
| QtCore.Qt.RightToolBarArea)
self.addToolBar( QtCore.Qt.LeftToolBarArea , self.toolbar )
self.toolbar.topLevelChanged.connect(self.handle_floating)
def handle_floating(self, event):
# The topLevel parameter is true
# if the toolbar is now floating
if not event:
# If the toolbar no longer floats,
# then calculate the position where the
# toolbar is located currently.
self.toolbar_pos = None
print "Get position: ?"
def main():
app = QtGui.QApplication(sys.argv)
ex = Example()
ex.setGeometry(300, 300, 300, 200)
ex.setWindowTitle('Toolbar example')
ex.show()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
The QMainWindow class already has APIs for this: i.e. saveState and restoreState. These can be used to save and restore the state of all the toolbars and dock-widgets in your application.
To use them, you first need to make sure that all your toolbars and dock-widgets are given a unique object-name when they are created:
class Example(QtGui.QMainWindow):
...
def initUI(self):
...
self.toolbar = QtGui.QToolBar(self)
self.toolbar.setObjectName('foobar')
Then you can override closeEvent to save the state:
class Example(QtGui.QMainWindow):
...
def closeEvent(self, event):
with open('/tmp/test.conf', 'wb') as stream:
stream.write(self.saveState().data())
(NB: I've just used a temporary file here for testing, but it would obviously be much better to use something like QSettings in your real application).
Finally, you can restore the state that was saved previously:
class Example(QtGui.QMainWindow):
def __init__(self, parent=None):
...
self.initUI()
try:
with open('/tmp/test.conf', 'rb') as stream:
self.restoreState(QtCore.QByteArray(stream.read()))
except IOError:
pass
I have a PhotoImage in tkinter called al_p4 but I want to be able to print the file path of the image. Can anyone help. Here is my code:
al_p4 = Image.open("Media/DVD/image.jpg").resize((100, 150), Image.ANTIALIAS)
al_p4 = ImageTk.PhotoImage(al_p4)
Thanks in advance guys ;)
Because I'm still having trouble interpreting exactly what you mean, here are four different answers regarding how to go about printing.
If you simply need to print it and the path will always be constant, use:
print("Media/DVD/image.jpg")
If you need to print something and the path will be different, try:
filepath = "Media/DVD/image.jpg"
al_p4 = Image.open(filepath).resize((100, 150), Image.ANTIALIAS)
al_p4 = ImageTk.PhotoImage(al_p4)
print(filepath)
If you need to print something to a widget, it's going to depend on the kind of widget you want to use. For something small like a file path, a label would probably be good. Look at effbot's documentation for the label widget for more details.
If you want to redirect all print statements to a widget, which can be useful depending on how your GUI is designed, create a class to redirect stdout. Here's an example with a text widget:
import sys
import Tkinter
def nothing():
print("Nothing")
class Application(Tkinter.Frame):
def __init__(self, master = None):
Tkinter.Frame.__init__(self, master)
self.button = Tkinter.Button(text = "Button 1", command = nothing)
self.button.pack()
class StdoutRedirector(Tkinter.Text):
def __init__(self):
Tkinter.Text.__init__(self)
def write(self, message):
printout.insert(Tkinter.END, message)
printout = StdoutRedirector()
printout.pack()
sys.stdout = printout
root = Tkinter.Tk()
app = Application(root)
app.mainloop()
I'm new to coding, so I'll try the best I can =)
Quick answer:
You need to use .filename in the PIL object (Don't works on TK object)
#This is the image:
al_p4 = Image.open("Media/DVD/image.jpg").resize((100, 150), Image.ANTIALIAS)
#This is to show in Tkinter, Notice I added ..._TK
al_p4_TK = ImageTk.PhotoImage(al_p4)
#This is the filepath I think you want:
print(al_p4.filename)
The following code is written using selenium python web driver which is run in saucelabs.I am providing the browser name,version and platform in a list,how do i do the same by providing the browser details through command line arguments? I am using py.test to execute the test cases.
import os
import sys
import httplib
import base64
import json
import new
import unittest
import sauceclient
from selenium import webdriver
from sauceclient import SauceClient
# it's best to remove the hardcoded defaults and always get these values
# from environment variables
USERNAME = os.environ.get('SAUCE_USERNAME', "ranjanprabhub")
ACCESS_KEY = os.environ.get('SAUCE_ACCESS_KEY', "ecec4dd0-d8da-49b9-b719-17e2c43d0165")
sauce = SauceClient(USERNAME, ACCESS_KEY)
browsers = [{"platform": "Mac OS X 10.9",
"browserName": "chrome",
"version": ""},
]
def on_platforms(platforms):
def decorator(base_class):
module = sys.modules[base_class.__module__].__dict__
for i, platform in enumerate(platforms):
d = dict(base_class.__dict__)
d['desired_capabilities'] = platform
name = "%s_%s" % (base_class.__name__, i + 1)
module[name] = new.classobj(name, (base_class,), d)
return decorator
#on_platforms(browsers)
class SauceSampleTest(unittest.TestCase):
def setUp(self):
self.desired_capabilities['name'] = self.id()
sauce_url = "http://%s:%s#ondemand.saucelabs.com:80/wd/hub"
self.driver = webdriver.Remote(
desired_capabilities=self.desired_capabilities,
command_executor=sauce_url % (USERNAME, ACCESS_KEY)
)
self.driver.implicitly_wait(30)
def test_sauce(self):
self.driver.get('http://saucelabs.com/test/guinea-pig')
assert "I am a page title - Sauce Labs" in self.driver.title
comments = self.driver.find_element_by_id('comments')
comments.send_keys('Hello! I am some example comments.'
' I should be in the page after submitting the form')
self.driver.find_element_by_id('submit').click()
commented = self.driver.find_element_by_id('your_comments')
assert ('Your comments: Hello! I am some example comments.'
' I should be in the page after submitting the form'
in commented.text)
body = self.driver.find_element_by_xpath('//body')
assert 'I am some other page content' not in body.text
self.driver.find_elements_by_link_text('i am a link')[0].click()
body = self.driver.find_element_by_xpath('//body')
assert 'I am some other page content' in body.text
def tearDown(self):
print("Link to your job: https://saucelabs.com/jobs/%s" % self.driver.session_id)
try:
if sys.exc_info() == (None, None, None):
sauce.jobs.update_job(self.driver.session_id, passed=True)
else:
sauce.jobs.update_job(self.driver.session_id, passed=False)
finally:
self.driver.quit()
So this is a bit complicated because you can pass an array of browsers into the #on_platforms decorator. My solution will only work for a single browser, as it looks like that's what you're doing right now.
For the current, single browser, situation -- you're looking for argparse. Here's my suggested fix:
import argparse
def setup_parser():
parser = argparse.ArgumentParser(description='Automation Testing!')
parser.add_argument('-p', '--platform', help='Platform for desired_caps', default='Mac OS X 10.9')
parser.add_argument('-b', '--browser-name', help='Browser Name for desired_caps', default='chrome')
parser.add_argument('-v', '--version', default='')
args = vars(parser.parse_args())
return args
desired_caps = setup_parser()
browsers = [desired_caps]
print browsers
But if you're looking to test multiple browsers (which I suggest you do!), you should not try and use command line arguments for the desired_caps of each individual browser. You should instead load a json config file for the browsers and the desired_caps for each one that you want Sauce to run.
Maybe have a different config file for each set of browsers, and then use command line arguments to pass in the config files you want to load.