首页 > 解决方案 > 将控制选项卡从一个 UI 插入到另一个 UI

问题描述

强文本

我是 python 新手,上图是两个 UI,我试图将右侧 UI 中的两个选项卡插入左侧 UI。但是我遇到了一些错误,不知道如何解决。现在下面是左侧UI的原始编码

import tkinter as tkk
from tkinter import *
from tkinter import messagebox
import os.path
import hashlib
import sys
import time
import getpass
from tkinter import filedialog
import platform
import getpass
import os,sys
import tkinter.font as font
from tkinter import ttk
from tkinter import StringVar
import Consts
import shutil
class Page(tkk.Frame):
    def __init__(self, *args, **kwargs):
        tkk.Frame.__init__(self, *args, **kwargs)
    def show(self):
        self.lift()
class Page1(Page):
   def __init__(self, *args, **kwargs):
       Page.__init__(self, *args, **kwargs,bg='white')
       my_system=platform.uname()

#computer information
   comsys=my_system.system
   comnode=my_system.node
   comrel=my_system.release
   comver=my_system.version
   commac=my_system.machine
   compro=my_system.processor
   comuser=getpass.getuser()

   label1 = tkk.Label(self,  text="System: "+comsys,bg='white')
   label1.grid(row=1,column=1,pady=10,sticky='w')
   label2 = tkk.Label(self, text="Computer Name: "+comnode,bg='white')
   label2.grid(row=2,column=1,pady=10,sticky='w')
   label3 = tkk.Label(self, text="Release: "+comrel,bg='white')
   label3.grid(row=3,column=1,pady=10,sticky='w')
   label4 = tkk.Label(self, text="Version: "+comver,bg='white')
   label4.grid(row=4,column=1,pady=10,sticky='w')
   label5 = tkk.Label(self, text="Machine: "+commac,bg='white')
   label5.grid(row=5,column=1, pady=10,sticky='w')
   label6 = tkk.Label(self, text="Processor: "+compro,bg='white')
   label6.grid(row=6,column=1, pady=10,sticky='w')
   label7 = tkk.Label(self, text="Username: "+comuser,bg='white')
   label7.grid(row=7,column=1,pady=10,sticky='w')

#computer usage hold first, no idea how to do

class Page2(Page):
   def __init__(self, *args, **kwargs):
   Page.__init__(self, *args, **kwargs,bg='white')

   tabControl=ttk.Notebook(self)
   
   qsFrame = ttk.Frame(tabControl)
   fsFrame = ttk.Frame(tabControl)
   csFrame = ttk.Frame(tabControl)
   
   #tab
   tabControl.add(qsFrame, text='Quick Scan')
   tabControl.add(fsFrame, text='Full Scan')
   tabControl.add(csFrame, text='Custom Scan')

   tabControl.pack(expand=1,fill="both")


class Page3(Page):
   def __init__(self, *args, **kwargs):
       Page.__init__(self, *args, **kwargs,bg='white')
       label = tkk.Label(self, text="This is page 3")
       label.grid(row=2,column=1)
       def mytools():
            total, used, free = shutil.disk_usage("/")
            print("Total:%d GB" %(total // (2**30)))
            print("Used:%d GB" %(used // (2**30)))
            print("Free:%d GB" %(free // (2**30)))

            if free <= total/2:
                clean = os.popen('Cleanmgr.exe/ sagerun:1').read()
                #print(clean)
   def btn1():
        if __name__ =="__main__":
            mytools()
   button1=ttk.Button(self,text="Clean Up",command=btn1)
   button1.grid(row=3,column=2)

class Page4(Page):
   def __init__(self, *args, **kwargs):
       Page.__init__(self, *args, **kwargs,bg='white')
       label = tkk.Label(self, text="This is page 4")
       label.grid(row=2,column=1)       

class MainView(tkk.Frame):
    def __init__(self, *args, **kwargs):
        tkk.Frame.__init__(self, *args, **kwargs)
        p1 = Page1(self)
        p2 = Page2(self)
        p3 = Page3(self)
        p4 = Page4(self)

        buttonframe = tkk.Frame(self)
        container = tkk.Frame(self,bg='white')
        buttonframe.pack(side="left", fill="x", expand=False)
        container.pack(side="left", fill="both", expand=True)

        buttonframe.grid_rowconfigure(0,weight=1)
        buttonframe.grid_columnconfigure(0,weight=1)
        container.grid_rowconfigure(0,weight=1)
        container.grid_columnconfigure(0,weight=1)


        p1.place(in_=container, x=0, y=0, relwidth=1, relheight=1)
        p2.place(in_=container, x=0, y=0, relwidth=1, relheight=1)
        p3.place(in_=container, x=0, y=0, relwidth=1, relheight=1)
        p4.place(in_=container, x=0, y=0, relwidth=1, relheight=1)

    
        stats_btn = tkk.PhotoImage(file='C:/FYP/SecuCOM2022/icon&pic/stats.png')
        scanner_btn = tkk.PhotoImage(file='C:\FYP\SecuCOM2022\icon&pic\scanner.png')
        speedup_btn = tkk.PhotoImage(file='C:\FYP\SecuCOM2022\icon&pic\speedup.png')
        settings_btn = tkk.PhotoImage(file='C:\FYP\SecuCOM2022\icon&pic\settings.png')
    
        #logo
        logo=tkk.PhotoImage(file="C:\FYP\SecuCOM2022\icon&pic\g (1).png")
        label=tkk.Label(buttonframe,image=logo)
        label.grid(row=0,column=0, padx=10,pady=10)
        logo.image = logo

        b1 = tkk.Button(buttonframe, image=stats_btn, command=p1.show, borderwidth=0)
        b2 = tkk.Button(buttonframe, image=scanner_btn, command=p2.show, borderwidth=0)
        b3 = tkk.Button(buttonframe, image=speedup_btn, command=p3.show, borderwidth=0)
        b4 = tkk.Button(buttonframe, image=settings_btn, command=p4.show, borderwidth=0)

        b1.image = stats_btn
        b2.image = scanner_btn
        b3.image = speedup_btn
        b4.image = settings_btn

        b1.grid(row=1,column=0,padx=10,pady=10)
        b2.grid(row=2,column=0,padx=10,pady=10)
        b3.grid(row=3,column=0,padx=10,pady=10)
        b4.grid(row=4,column=0,padx=10,pady=10)


if __name__ == "__main__":
    root= Tk()
    main = MainView(root)
    main.pack(side="top", fill="both", expand=True)
    main.grid_rowconfigure(0,weight=1)
    main.grid_columnconfigure(0,weight=1)
    root.title("SecuCOM2022")
    root.geometry("600x300")
    root.maxsize(600,375)
    root.minsize(600,375)
    root.iconbitmap('C:\FYP\SecuCOM2022\icon&pic\g.png')
    root.mainloop()


root.mainloop()
#GUI end`

下面是右侧的 UI 编码,它有多个文件。我只显示与 UI 相关的文件。

常量.py

ENTRY_WIDTH = 50

文件报告表.py

from tkinter import filedialog
from tkinter import messagebox
from tkinter import ttk
from tkinter import StringVar
import time
import os.path
import sys
from VTPackage import Consts
class FileReportTab:

def __init__(self, root, frame, vtClient):
    self.root = root
    self.frame = frame
    self.vtClient = vtClient

    self.mainVTURLframe = ttk.LabelFrame(frame, text=' File report')
    self.mainVTURLframe.grid(column=0, row=1, padx=8, pady=4)

    ttk.Label(self.mainVTURLframe, text="Progress:").grid(column=0, row=1, sticky='W')  # <== right-align
    self.progressBar = ttk.Progressbar(self.mainVTURLframe, orient='horizontal', length=300, mode='determinate')
    self.progressBar.grid(column=1, row=1)

    ttk.Label(self.mainVTURLframe, text="File path:").grid(column=0, row=2, sticky='W')  # <== right-align
    self.filePath = StringVar()
    filePathEntry = ttk.Entry(self.mainVTURLframe, width=Consts.ENTRY_WIDTH, textvariable=self.filePath, state='readonly')
    filePathEntry.grid(column=1, row=2, sticky='W')

    ttk.Label(self.mainVTURLframe, text="Status:").grid(column=0, row=3, sticky='W')  # <== right-align
    self.status = StringVar()
    statusEntry = ttk.Entry(self.mainVTURLframe, width=Consts.ENTRY_WIDTH, textvariable=self.status, state='readonly')
    statusEntry.grid(column=1, row=3, sticky='W')

    ttk.Label(self.mainVTURLframe, text="Positive Indications:").grid(column=0, row=4, sticky='W')  # <== right-align
    self.positiveIndications = StringVar()
    positiveIndicationsEntry = ttk.Entry(self.mainVTURLframe, width=Consts.ENTRY_WIDTH, textvariable=self.positiveIndications, state='readonly')
    positiveIndicationsEntry.grid(column=1, row=4, sticky='W')

    ttk.Label(self.mainVTURLframe, text="SHA1:").grid(column=0, row=5, sticky='W')  # <== right-align
    self.sha1 = StringVar()
    sha1Entry = ttk.Entry(self.mainVTURLframe, width=Consts.ENTRY_WIDTH, textvariable=self.sha1, state='readonly')
    sha1Entry.grid(column=1, row=5, sticky='W')

    ttk.Label(self.mainVTURLframe, text="SHA256:").grid(column=0, row=6, sticky='W')  # <== right-align
    self.sha256 = StringVar()
    sha256Entry = ttk.Entry(self.mainVTURLframe, width=Consts.ENTRY_WIDTH, textvariable=self.sha256, state='readonly')
    sha256Entry.grid(column=1, row=6, sticky='W')

    chooseFileButton = ttk.Button(self.mainVTURLframe, text="Choose File", width=40, command=self._scanFile).grid(column=1, row=0)

    self.scanCheckingTimeInterval = 25000  # This is the amount of time we are going to wait before asking VT again if it already processed our scan request

    for child in self.mainVTURLframe.winfo_children():
        child.grid_configure(padx=4, pady=2)

def showResults(self, results):
    try:
        #self.file_Path = self.filePath
        self.sha1.set(results["sha1"])
        self.sha256.set(results["sha256"])
        self.positiveIndications.set(results["positives"]) 
        if results["positives"] == 0:
            messagebox.showwarning("Analysis Info","File is Safe.\nOur Scanners found nothing Malicious")
        elif results["positives"] <= 5:
            messagebox.showwarning("Analysis Alert", "Given File may be Malicious")
        elif results["positives"] >= 5:
            messagebox.showwarning("Analysis Alert", f"Given File is Malicious.\nAdvice you remove the file from your System!")
            res = messagebox.askyesno("Analysis Alert","The given file is highly Malicious.\nDo you want to Delete it permanently?")
            if res == 1:
                print("Attemting to delete file...")
                time.sleep(1)
                os.remove(self.filePath1)
                
                #if os.PathLike(_scanFile.filePath):
                 #   os.remove(self.filePath)
            else:
                print("This file cannot be deleted. Please do not use the fie. It's Malicious")
    except Exception as e:
        messagebox.showerror('Error', e)

def checkStatus(self):
    try:
        self.scanResult = self.vtClient.get_file_report(self.scanID)
        print(self.scanResult)
        if self.scanResult["response_code"] == -2:  # By reading the next line, you can understand what is the meaning of the -2 response ode
            self.status.set("Scanning...")
            self.progressBar['value'] = self.progressBar['value'] + 5
            self.root.update_idletasks()
            self.mainVTURLframe.after(self.scanCheckingTimeInterval, self.checkStatus)

        else:
            self.hasScanFinished = True
            self.showResults(self.scanResult)
            self.status.set("Finished!")

            self.progressBar['value'] = 100
    except Exception as e:
        if "To much API requests" in str(e):
            pass

def _scanFile(self):
    try:
        self.progressBar['value'] = 0
        self.filePath1 = filedialog.askopenfilename(initialdir="/", title="Select file for VT", filetypes=(("EXE files", "*.exe"), ("all files", "*.*")))

        if (self.filePath):  # Only if the user chose a file, we will want to continue the process
            self.filePath.set(self.filePath1)
            self.status.set("Sending file...")
            self.progressBar['value'] = 10
            
            self.root.update_idletasks()
            self.scanID = self.vtClient.scan_file(self.filePath1)
            self.hasScanFinished = False
            if not self.hasScanFinished:
                self.scanResult = self.vtClient.get_file_report(self.scanID)
                print(self.scanResult)
                self.checkStatus()
                # We could have been using time.sleep() or time.wait(), but then our UI would get stuck.
                # by using after, we are initiating a callback in which does not blocks our event loop
    except Exception as e:
        messagebox.showerror('Error', e)

URLreportTab.py

from tkinter import ttk
from tkinter import StringVar
from VTPackage import Consts

class URLreportTab:
def __init__(self, root, frame, vtClient):
    self.root = root
    self.frame = frame
    self.mainVTURLframe = ttk.LabelFrame(frame, text=' URL report tab!')

    # using the tkinter grid layout manager
    self.mainVTURLframe.grid(column=0, row=0, padx=8, pady=4)
    ttk.Label(self.mainVTURLframe, text="URL:").grid(column=0, row=0, sticky='W')  # What does sticky does?      Sticky sayes where to stick the label to : N,S,E,W
    urlEntry = ttk.Entry(self.mainVTURLframe, width=Consts.ENTRY_WIDTH)
    urlEntry.grid(column=1, row=0, sticky='E')

    ttk.Label(self.mainVTURLframe, text="Positive Indications:").grid(column=0, row=1, sticky='W')  # <== right-align
    Positive = StringVar()
    PositiveEntry = ttk.Entry(self.mainVTURLframe, width=Consts.ENTRY_WIDTH, textvariable=Positive, state='readonly')
    PositiveEntry.grid(column=1, row=1, sticky='W')

    ttk.Label(self.mainVTURLframe, text="Detections:").grid(column=0, row=2, sticky='W')  # <== right-align
    detections = StringVar()
    detectionsEntry = ttk.Entry(self.mainVTURLframe, width=Consts.ENTRY_WIDTH, textvariable=detections, state='readonly')
    detectionsEntry.grid(column=1, row=2, sticky='W')

    self.notificationFrame = ttk.LabelFrame(self.frame, text=' Notifications', width=40)
    # using the tkinter grid layout manager
    self.notificationFrame.grid(column=0, row=1, padx=8, pady=10, sticky='W')

    ttk.Label(self.notificationFrame, text="Errors:").grid(column=0, row=0, sticky='W')  # <== increment row for each
    Error = StringVar()
    ErrorEntry = ttk.Entry(self.notificationFrame, width=Consts.ENTRY_WIDTH, textvariable=Error, state='readonly')

    ErrorEntry.grid(column=1, row=0, sticky='W')

    def _cleanErrorMessage():  # We could have been doing this without a function, but it is more neat that way
        Error.set("")

    def _getReport():
        # the _ notation before a function means that this function is internal to the class only. As python cannot really prevent you from using it outside the class (as C# for example) the notation is being used to warn other developers not to call this function outside the class
        try:
            _cleanErrorMessage()  # Starting with cleaning the error message bar
            if not urlEntry.get():
                print('Please enter a URL')
                Error.set("Please enter a URL!")
                return

            urlToCheck = urlEntry.get()
            response = vtClient.get_url_report(urlToCheck)
            print(response)
            Positive.set(response["positives"])
            scans = response["scans"]

            findings = set()
            for key, value in scans.items():
                if value["detected"]:
                    findings.add(value["result"])
            detections.set(",".join([str(finding) for finding in findings]))

        except Exception as e:
            print(e)
            Error.set(e)

    checkURLinVTButton = ttk.Button(self.mainVTURLframe, text='Check Now!', command=_getReport).grid(column=2, row=0)

    # Instead of setting padding for each UI element, we can just iterate through the children of the main UI object.
    for child in self.mainVTURLframe.winfo_children():
        child.grid_configure(padx=4, pady=2)
    for child in self.notificationFrame.winfo_children():
        child.grid_configure(padx=4, pady=2)

VTApp.py

import tkinter as tk
import configparser
from tkinter import Menu
from tkinter import ttk
from tkinter import messagebox

from VTPackage import URLreportTab
from VTPackage import FileReportTab

from VTPackage import VTClient

config = configparser.ConfigParser()
config.read('config.ini')

class VTApp:
def __init__(self):
    # Loading the config file
    self.config = configparser.ConfigParser()
    self.config.read('config.ini')
    self.virusTotalAPIkey = config['VirusTotal']['apiKey']

    self.vtClient = VTClient.VTClient(self.virusTotalAPIkey)
    self.root = tk.Tk()
    self.root.title("Virus Total UI")
    self.menuBar = Menu()
    self.root.config(menu=self.menuBar)
    self.fileMenu = Menu(self.menuBar, tearoff=0)
    self.fileMenu.add_command(label="New")
    self.fileMenu.add_separator()
    self.menuBar.add_cascade(label="File", menu=self.fileMenu)

    if not self.vtClient.is_API_key_valid():
        messagebox.showerror('Error', "API key is not valid! Check your config file")

    def _quit():
        self.root.quit()  # The app  will exist when this function is called
        self.root.destroy()
        exit()

    self.fileMenu.add_command(label="Exit", command=_quit)  # command callback
    self.tabControl = ttk.Notebook(self.root)  # Create Tab Control

    self.urlFrame = ttk.Frame(self.tabControl)
    self.urlTab = URLreportTab.URLreportTab(self.root, self.urlFrame, self.vtClient)
    self.tabControl.add(self.urlFrame, text='URL')

    self.fileFrame = ttk.Frame(self.tabControl)
    self.fileTab = FileReportTab.FileReportTab(self.tabControl, self.fileFrame, self.vtClient)
    self.tabControl.add(self.fileFrame, text='File')

    self.tabControl.pack(expand=1, fill="both")  # Pack to make visible

def start(self):
    self.root.mainloop()

主文件

from VTPackage import VTApp

vtApp = VTApp.VTApp()
vtApp.start()

这是原始代码,对不起间距错误,我从 vsc 复制并粘贴,似乎在 Class 之后出现了一些间距错误。所以基本上这是原始代码,我尝试像 import VTApp 和类 Page2 中的代码一样

vtApp = VTApp.VTApp()
vtApp.start()

并更改 VTApp.py 中的一些编码,但它不起作用....有谁知道如何使脚本工作?我一直在尝试一个星期,但仍然无法得到解决方案。

标签: pythonuser-interfacetkinter

解决方案


您不能在 tkinter 中将小部件从一个窗口移动到另一个窗口。您将不得不在另一个窗口中重新创建选项卡。


推荐阅读