0

WHAT DO I WANT TO GET? If the condition of the second.py file is true then "ok" will be printed in the textbox of the main.py file. If the confition is False, then "No" will be printed in the same textbox.

main.py is a file that is opened by the Home.py file. So initially there is the Home.py file which opens the main.py file inside it. The main.py file executes the second.py file. I only posted the main and second file, because the main file opens correctly in the home file

Home.py > main.py > second.py

In the main.py file I have a textobox and a button. To be precise, they are both in a class of the main file, but in the code I carry only the minimum necessary for the example.By clicking on the button, I would like to import the code located in another class of another file (second.py file). The code of the secondary.py file is used to generate text (with conditions) to be printed in the textobox of the main.py file. It's a simple case, but something is wrong.

The error is:

TypeError: __init__() missing 1 required positional argument: 'master'

Main.py

from tkinter import *
from tkinter import ttk
import tkinter as tk


class Home(tk.Frame): #update
    def __init__(self, master): #update
        super().__init__(master, **kw) #update

        #class import from other file
        from Folder.Folder2 import second
        k = second.Print

        #i want to print the output here  
        self.textobox = tk.Text(master, width=33, height=10, font=('helvetic', 12))
        self.textobox.place(x=30, y=40)

        self.button = Button(master, text="Ok", command= lambda: [one_function(), two_function()])
        self.button.pack()

second.py

import sqlite3
    
class Print:
    def __init__(self, master, **kw):
        super().__init__(master, **kw)
    
    
        self.conn = sqlite3.connect('...')
        self.cursor = conn.cursor()
    
        self.cursor.execute('SELECT x, y FROM Table')
        self.element = cursor.fetchone()
         
        self.cursor.execute("SELECT day FROM quantity")
        self.day = cursor.fetchone()

        #condition to print text in the textbox of the main.py file    
        if self.day == "Monday" and (self.element[0]) >= (self.element[1]):
            textobox.insert(tk.END, "ok")
    
        else:
            textobox.insert(tk.END, "no")

The database is very simple:

CREATE TABLE "Table" (
    "id"    INTEGER,
    "x" INTEGER, #for example 23
    "y" INTEGER, #for example 12
    PRIMARY KEY("id")
);


CREATE TABLE "quantity" (
    "id"    INTEGER,
    "day"   INTEGER, #for example Monday
    PRIMARY KEY("id")
);
  • 1
    `k = second.Print` What is the purpose of this line? You never refer to `k`, and there aren't parentheses after, so you're not actually creating an _instance_ of `Print`. – John Gordon Jan 14 '22 at 01:56
  • In your own words: what is a class, and what is the purpose of creating a class? – Karl Knechtel Jan 14 '22 at 01:58
  • Why do you want to import inside the method? Just put the `import` at top-level, then you can refer to it in the class methods. – Barmar Jan 14 '22 at 01:59
  • @JohnGordon I am new to Python and have never imported a class from another file. I have read some tutorials, but I don't understand. Could you show me an answer of how I can change my code? Obviously in case of correct solution, I will vote on your answer. Thank you –  Jan 14 '22 at 02:07
  • @Barmar Could you show me how I can please? I am new to Python and have never imported a class from another file. I have read some tutorials, but I don't understand. Could you show me an answer of how I can change my code? Obviously in case of correct solution, I will vote on your answer. Thank you –  Jan 14 '22 at 02:08
  • Just put `from second import Print` at the top with all the other imports. – Barmar Jan 14 '22 at 02:11
  • I don't know what you _intended_ to do, therefore I cannot tell you what the correct solution is. – John Gordon Jan 14 '22 at 02:14
  • @Barmar Tried. That's no good. I have no errors, but nothing is printed in the textbox of the main file. Did I successfully import the class with k = second.Print? Or is the problem about selfs or masters? Can you help me? Thank you –  Jan 14 '22 at 02:26
  • As I said before, `k = second.Print` is missing the parentheses after, so you are _not_ creating an instance. Did you mean to include the parentheses `k = second.Print()`? – John Gordon Jan 14 '22 at 02:38
  • @JohnGordon If I try to add () to k = second.Print, I get the error: TypeError: __init __ () missing 1 required positional argument: 'master' –  Jan 14 '22 at 02:40
  • Well, yes, you defined the `Print()` class to require an argument, and you're not passing one in... – John Gordon Jan 14 '22 at 02:54
  • @JohnGordon And how do I solve? Thank you –  Jan 14 '22 at 02:57
  • 1
    In the `Print` class, why does `__init__()` call `super()`? That is only useful for classes that inherit from another class, which `Print` does not do... – John Gordon Jan 14 '22 at 03:02
  • 1
    There are many typos in `second.py`, e.g. `conn.cursor()` should be `self.conn.cursor()`, `cursor.execute(...)` should be `self.cursor.execute(...)`. Also `self.day` is a `tuple` and so `if self.day == "Monday"` will be always false. – acw1668 Jan 14 '22 at 03:13
  • @acw1668 Yes, you're right, it was my distraction. While I didn't understand how I could solve for if self.day == "Monday". However I think the main problem is with def __init __ (self, master): super () .__ init __ () of both main.py and second.py. I am studying the tutorials of the classes, but I cannot solve. Could you show me the answer please? Obviously in case your answer helps me to solve the problem, I will vote for you. Thank you –  Jan 14 '22 at 03:32
  • @acw1668 I improved my question. I added the error and changed the code. can you help me? Thank you –  Jan 14 '22 at 03:44

1 Answers1

0

There are many typos in second.py:

  • conn.cursor() should be self.conn.cursor()
  • cursor.execute(...) should be self.cursor.execute(...)

Other than typos:

  • super().__init__(...) should not be called
  • Table is a keyword in SQLite3, so if it is used as table name, you need to put it inside quotes, e.g. "Table". Suggest to use another name instead.
  • textobox is undefined (it is an instance variable inside Home class in main.py
  • tk.END is undefined
  • master and **kw arguments are not necessary as it is not used
  • self.day is either a tuple (if record returned) or None

Also Suggest to pass self.textobox in Home class to Print class instead.

Below is a modified second.py:

import sqlite3

class Print:
    def __init__(self, textbox):  # added textbox argument

        self.conn = sqlite3.connect('...')
        self.cursor = self.conn.cursor()

        self.cursor.execute('SELECT x, y FROM "Table"')
        self.element = self.cursor.fetchone()

        self.cursor.execute("SELECT day FROM quantity")
        self.day = self.cursor.fetchone()

        #condition to print text in the textbox of the main.py file
        if (self.day and self.day[0] == "Monday") and (self.element and self.element[0] >= self.element[1]):
            textbox.insert("end", "ok")
        else:
            textbox.insert("end", "no")

For main.py:

  • super().__init__() should not be called as well
  • k = second.Print should be k = second.Print(...) and it should be called after self.textobox() is created
  • one_function() and two_function() are undefined. (Are they defined elsewhere?)

Below is the modified main.py:

import tkinter as tk
from Folder.Folder2 import second

class Home:
    def __init__(self, master):

        #i want to print the output here
        self.textobox = tk.Text(master, width=33, height=10, font=('helvetic', 12))
        self.textobox.place(x=30, y=40)

        self.button = tk.Button(master, text="Ok", command= lambda: [one_function(), two_function()])
        self.button.pack()

        k = second.Print(self.textobox) # pass self.textobox to Print class

main = tk.Tk()
main.geometry("400x300")
my_gui = Home(main)
main.mainloop()

Note that it is bad practice to import module as below:

from tkinter import *
import tkinter as tk

because wildcard import is not recommended and tkinter module has been import twice. Use the second import is recommended.


Updated main.py based on changes in question:

import tkinter as tk
from Folder.Folder2 import second

class Home(tk.Frame):
    def __init__(self, master, **kw):
        super().__init__(master, **kw)

        #i want to print the output here
        self.textobox = tk.Text(self, width=33, height=10, font=('helvetic', 12))
        self.textobox.place(x=30, y=40)

        self.button = tk.Button(self, text="Ok", command= lambda: [one_function(), two_function()])
        self.button.pack()

        k = second.Print(self.textobox)

main = tk.Tk()
main.geometry("400x300")
my_gui = Home(main)
my_gui.pack(fill="both", expand=1)
main.mainloop()

Note that I have used self instead of master when creating the button and the textbox.

acw1668
  • 40,144
  • 5
  • 22
  • 34
  • Thank you,but there is a class inheritance problem. I get AttributeError: 'Home' object has no attribute 'tk'.I changed the my first 3 rows of class Home.Look.Also,i may not have spoken well about heredity.On the web i found this question from another user https://stackoverflow.com/questions/70043853/click-on-a-button-and-open-the-content-in-a-frame-direct-way-in- frame-and-way-w and i copied and pasted the code.I use a menu like this.Home py is the main page.Inside home.py the main.py file opens.Clicking a button in main.py opens the second.py script.I would like to view output in main.py –  Jan 14 '22 at 04:39
  • @NathanMüller Answer updated. – acw1668 Jan 14 '22 at 04:46
  • Should I use these? I don't currently use these 5 staves and the file loads and displays correctly without these. I mean main.geometry("400x300") my_gui = Home(main) my_gui.pack(fill="both", expand=1) main.mainloop() –  Jan 14 '22 at 04:49
  • I don't know what your actual code is. My answer is based on the code provided. You need to understand what my answer does and apply the logic to your actual code. – acw1668 Jan 14 '22 at 04:51
  • My mistake. Excuse me. Now i cancel main=Tk() my_gui = Home(main) main.geometry("400x300") main.mainloop(). Excuse me. I was confused.I had used them previously to simplify the question, but i don't really use them. Excuse me. I got mixed up with the code. Excuse me. Now i'll try your new changes, then in a few minutes i'll get back to you. Thank you –  Jan 14 '22 at 04:57
  • It seems to work, but there is a problem with the self.day condition. In the condition I always receive False and therefore "No" is always printed in the textbox even when "Ok" should be printed. How come? Another question: why did you replace tk.END with "end"? –  Jan 14 '22 at 05:36
  • You should print out the content of `self.day` and see whether it is what you expect. Since `second.py` does not import `tkinter`, `tk.END` is undefined, so I used `"end"`. – acw1668 Jan 14 '22 at 05:38
  • Okay, I understand. However I did a simple test. I tried to create the condition only if self.day == "Monday": textobox.insert (tk.END, "ok") and its else. I checked the database and it says Monday, so it should print "Ok, but it prints" No ". I tried to print with print and it prints ('Monday',) –  Jan 14 '22 at 05:45
  • Did you use `self.day[0] == "Monday"` as mentioned in my answer? Also did you check whether `self.element` checking returns what you expect? – acw1668 Jan 14 '22 at 05:55
  • No, I didn't do that. To quickly roll the code to run this test I had accidentally deleted [0]. Excuse me. Now everything works correctly, even if I had a little problem (I'll ask another question), because my question code has been simplified, but the cursor.execute a ,[value]) that could not be recovered in the class of the file. So I tested your answer without this. However, I think everything works fine and I thank you. As soon as I can, I will also vote on your answer –  Jan 14 '22 at 06:02