Question

I have a program written in IDLE3.3 and tkinter where I don't know where to place the mainloop(). The program creates a systray icon that creates a little note if you click on "new note" in the context menu. If there is the line "self.root.mainloop()" at the end of Note.init(), the note is shown, but only one note. if I create a second one, the first note is dead and nothing further happens. But if I don't call the mainloop() in the init-method, i see that there a several notes created because it is printed in the shell. So the question is, where should I place the mainloop so that every newly created notw is shown and works? Sorry for that possibly stupid question but I can't figure it out.

from tkinter import *
import sys
from PyQt4.QtGui import *
import threading


class Note():

    yellow=["#e7e37c","#d9d574"]

    def __init__(self,noteset=None, properties=None):
        self.root=Tk()
        self.noteset=noteset
        self.properties=properties
        self.screen_width = self.root.winfo_screenwidth()      
        self.screen_height = self.root.winfo_screenheight()    
        print("No initial properties to load => creating new note")
        self.notecolor=self.yellow[0]
        self.gripcolor=self.yellow[1]
        self.root.overrideredirect(1) 
        self.text=""
        self.font="arial"
        self.fontsize=10  
        self.sizeX=250 
        self.sizeY=200
        self.posX=int(self.screen_width/2 - self.sizeX/2)   
        self.posY=int(self.screen_height/2 - self.sizeY/2)
        self.root.wm_geometry("%sx%s+%s+%s"   %(self.sizeX,  self.sizeY,  self.posX,  self.posY) )           
        self.root.wm_attributes("-topmost",1)
        self.GUI()
        self.bindings()

        self.root.mainloop()

    def bindings(self):
        self.frmGRIP.bind("<ButtonPress-1>", self.StartMove)
        self.frmGRIP.bind("<ButtonRelease-1>", self.StopMove)
        self.frmGRIP.bind("<B1-Motion>", self.OnMotion)

    def StartMove(self, event):
        self.startx = event.x
        self.starty = event.y
    def OnMotion(self, event):           
        mousex,mousey=self.root.winfo_pointerxy()
        self.root.geometry("+%s+%s" % (mousex-self.startx, mousey-self.starty))
    def StopMove(self, event):
        self.posX = self.root.winfo_x()
        self.posY = self.root.winfo_y()

    def GUI(self):                 
        self.frmTOP=Frame(master=self.root,height=15)
        self.frmBOTTOM=Frame(master=self.root,width=300,height=300)
        self.frmGRIP=Frame(self.frmTOP,bg=self.gripcolor,height=15)
        self.frmRESIZE=Frame(self.frmBOTTOM,width=300,height=10)
        self.frmTEXT=Frame(self.frmBOTTOM,bg=self.notecolor,width=300,height=300)
        self.frmRESIZE_empty=Frame(self.frmRESIZE,bg=self.notecolor,height=10)
        self.frmRESIZE_grip=Frame(self.frmRESIZE,bg=self.gripcolor,width=10,height=10)

        self.frmTOP.pack(fill=X,expand=NO)
        self.frmBOTTOM.pack(side=BOTTOM,fill=BOTH,expand=YES) 
        self.frmGRIP.pack(side=LEFT,fill=X,expand=YES)
        self.frmRESIZE.pack(side=BOTTOM,fill=X)        
        self.frmTEXT.pack(side=BOTTOM,fill=BOTH,expand=YES)
        self.frmRESIZE_empty.pack(side=LEFT,fill=X,expand=YES)
        self.frmRESIZE_grip.pack(side=LEFT,expand=NO)

        self.T=Text(self.frmTEXT,
                    height=6,width=30,
                    bd=0,wrap=WORD,pady=3,padx=5,
                    bg=self.notecolor,undo=1,
                    font=(self.font,self.fontsize)
                    )
        self.T.insert(END,self.text)
        self.T.pack(fill=BOTH,expand=YES)        

class Noteset():
    def __init__(self):
        self.notes = []
    def newNote(self):
        note=Note(noteset=self)
        self.notes.append(note)
        print(self.notes)
        return note

class Main():
    def __init__(self):
        self.N=Noteset()
        app = QApplication(sys.argv)

        trayIcon = QSystemTrayIcon(QIcon("J:\\python\\SimpleNotes.ico"), app)
        menu = QMenu()

        ActionNewNote = menu.addAction("new Note")
        ActionNewNote.triggered.connect(self.newNote)
        trayIcon.setContextMenu(menu)
        trayIcon.show()

        app.exec()

    def newNote(self):
        self.N.newNote()


Main()
Was it helpful?

Solution

You cannot successfully use Qt and Tkinter together. Also, if you remove Qt from the above you have the additional problem that you should not create more than once instance of Tk.

To answer your specific question, mainloop is normally the very last line of code that you execute. Since it is an infinite loop, any code after you call mainloop won't execute until the main window is destroyed.

The normal structure for a Tkinter application goes something like this:

import Tkinter as tk
class MyApp(...):
    def __init__(self, root, ...):
        ...
    ...

root = tk.Tk()
myApp(root)
root.mainloop()

OTHER TIPS

Its not a good idea to mix gui frameworks as each of the mainloops block each other, your better off to code the whole thing in one or the other.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top