Je voulais un outil de type GUI qui ouvre des pages avec la même balise de recherche à la fois sur les sites EC et les sites de publication de travail.
・ (La classe json est une amélioration de celle précédemment créée et en a fait une partie commune) ・ Implémentation de la classe de gestion de la combo de Tkinter et en a fait une partie commune -Définissez l'interface graphique avec la méthode principale, lisez les données et ouvrez la page Web sélectionnée par l'interface graphique.
・ Windows10 ・ Python 3.7.0 ・ Le développement est Pycharm
L'interface graphique ressemble à ceci.
webSiteDetails.json
{
"WebSiteA": {
"OnlyOpenPage": true,
"PageSet": [
"http://foobar.com",
"http://foobar.com",
"http://foobar.com",
"http://foobar.com",
"http://foobar.com",
"http://foobar.com",
"http://foobar.com",
"http://foobar.com",
"http://foobar.com"
]
},
"WebSiteB": {
"OnlyOpenPage": true,
"PageSet": [
"http://foobar.com",
"http://foobar.com"
]
},
"WebSiteC": {
"OnlyOpenPage": true,
"PageSet": [
"http://foobar.com",
"http://foobar.com",
"http://foobar.com",
"http://foobar.com"
]
},
"WebSiteD": {
"OnlyOpenPage": true,
"PageSet": [
"http://foobar.com",
"http://foobar.com",
"http://foobar.com",
"http://foobar.com"
]
},
"WebSiteE": {
"OnlyOpenPage": true,
"PageSet": [
"http://foobar.com",
"http://foobar.com",
"http://foobar.com"
]
}
}
La propriété "Only OpenPage" a été ajoutée Lors de l'examen de la mise en œuvre de la fonction de grattage à l'avenir Ouvrez-le simplement Prime de traitement de grattage, Je voulais faire une distinction.
JsonHandler.py
import json
class JsonHandler:
def __init__(self, jsonPath):
#Lire le fichier json
self.file = open(jsonPath, 'r', encoding="utf-8_sig")
self.jsonData = json.load(self.file)
#Obtenir les données JSON pour l'imbrication principale
def getParam_OneNest(self, args):
return self.jsonData[args]
#Obtenir la liste des données JSON du nid principal
def getAll_OneNest(self):
# list = []
# for d in self.jsonData.keys():
# list.append(d)
list = [d for d in self.jsonData.keys()]
return list
#Obtenir des données JSON pour l'imbrication secondaire
def getParam_TwoNest(self, args1, args2):
return self.jsonData[args1][args2]
def __del__(self):
#Fermer le fichier
self.file.close()
J'ai changé un peu celui que j'avais créé avant (*). Parce qu'il était nécessaire d'acquérir uniquement les données du nid principal à la fois. [※:https://qiita.com/dede-20191130/items/65b0f4c3c2b5c7f97546]
list = [d for d in self.jsonData.keys()]
Il s'agit d'un format d'inclusion de liste.
TkHandler_Combo_1.py
import tkinter as tk
import tkinter.ttk as ttk
class TkHandler_Combo_1:
"""Parties communes de l'interface graphique. Créer une zone de liste déroulante"""
def __init__(self, rootTitle='Titre', rootGeometry='640x480'):
#Créer un cadre racine
self.root = tk.Tk()
self.root.title(rootTitle)
#Taille de la fenêtre racine comme valeur d'argument
self.root.geometry(rootGeometry)
#Fermer le paramètre d'événement
self.root.protocol("WM_DELETE_WINDOW", self.onClosing)
self.frame = None
self.label = None
self.combo = None
self.button = None
self.isDestroyed = False
def createFrame(self):
#Créer un cadre
self.frame = ttk.Frame(self.root, width=self.root.winfo_width() - 20, height=self.root.winfo_height() - 20,
padding=10)
self.frame.pack()
def createLabel(self, myText="Veuillez sélectionner"):
#Créer une étiquette
self.label = ttk.Label(self.frame, text=myText, padding=(5, 5))
self.label.pack()
def createCombo(self, myWidth=None, myState='readonly', myValue=None, ):
#réglage de la largeur
myWidth = myWidth or self.frame.winfo_width() - 20
#Créer une zone de liste déroulante
self.combo = ttk.Combobox(self.frame, width=myWidth, state=myState)
self.combo["values"] = myValue
#Valeur par défaut(index=0)Mis à
self.combo.current(0)
#Placement de la liste déroulante
self.combo.pack(padx=5, pady=5, fill=tk.X)
def createButton(self, myText="Courir", myFunc=None):
"""Prenez une fonction comme argument"""
#Paramètres de fonction
myFunc = myFunc or (lambda: self.dummy())
#Créer un bouton
self.button = tk.Button(text=myText, command=lambda: myFunc(self.combo.get()))
#* ↑↑ Au début, c'était implémenté comme ça
# if myFunc:
# self.button = tk.Button(text=myText, command=lambda: myFunc(self.combo.get()))
# else:
# self.button = tk.Button(text=myText, command=lambda: self.dummy())
#Placement des boutons
self.button.pack(padx=5, pady=5, )
def dummy(self, arg=''):
pass
def mainLoop(self):
self.root.mainloop()
def onClosing(self):
self.root.destroy()
self.isDestroyed = True
def __del__(self):
if not self.isDestroyed:
self.root.destroy()
#Fermer les paramètres de l'événement
self.root.protocol("WM_DELETE_WINDOW", self.onClosing)
Une syntaxe qui définit une méthode appelée lorsque la fenêtre est fermée sans appuyer sur le bouton d'exécution. Effacez le cadre avant de fermer avec onClosing Empêche les erreurs lorsque le destructeur (fonction \ __ del__) fonctionne.
def createCombo(self, myWidth=None, myState='readonly', myValue=None, ):
#réglage de la largeur
myWidth = myWidth or self.frame.winfo_width() - 20
Si un argument est spécifié pour myWidth, il continuera à avoir cette valeur, Si l'argument par défaut Aucun est laissé, une valeur 20 plus petite que la valeur de largeur du cadre sera entrée.
Je me suis référé à cet article pour savoir comment utiliser ou. https://blog.pyq.jp/entry/python_kaiketsu_181016
La raison pour laquelle je n'ai pas mis "self.frame.winfo_width () -20" directement dans l'argument par défaut est Il semble que vous ne pouvez pas prendre les membres de champ de votre propre classe comme arguments. Si quelqu'un sait qu'il existe un moyen possible, faites-le moi savoir.
def createButton(self, myText="Courir", myFunc=None):
"""Prenez une fonction comme argument"""
#Paramètres de fonction
myFunc = myFunc or (lambda: self.dummy())
#Créer un bouton
self.button = tk.Button(text=myText, command=lambda: myFunc(self.combo.get()))
#* ↑↑ Au début, c'était implémenté comme ça
# if myFunc:
# self.button = tk.Button(text=myText, command=lambda: myFunc(self.combo.get()))
# else:
# self.button = tk.Button(text=myText, command=lambda: self.dummy())
Objet bouton Tkinter comme événement lorsqu'il est pressé Une fonction est affectée à l'argument de commande.
Par conséquent, lorsque la méthode createButton est appelée Vous devez préparer une fonction côté appelant.
Cependant, en en faisant une partie commune, Je voulais préparer un argument par défaut au cas où la fonction ne serait pas spécifiée.
Au début, j'ai essayé cela.
def createButton(self, myText="Courir", myFunc=lambda: pass):
Cela n'a pas fonctionné. Il semble difficile de définir la fonction lambda comme argument.
Par conséquent, définissez une méthode factice factice dans la classe. J'ai essayé de le remplacer.
Ici, comme mentionné ci-dessus, "vous ne pouvez pas prendre le membre du champ que votre propre classe a comme argument", donc J'ai écrit comme suit.
def createButton(self, myText="Courir", myFunc=None):
"""Prenez une fonction comme argument"""
# if myFunc:
# self.button = tk.Button(text=myText, command=lambda: myFunc(self.combo.get()))
# else:
# self.button = tk.Button(text=myText, command=lambda: self.dummy())
C'était bien, mais c'est un peu redondant Ecrire une expression qui définit le champ de bouton deux fois est deux fois plus difficile à gérer.
Par conséquent, il a été réécrit comme suit.
def createButton(self, myText="Courir", myFunc=None):
"""Prenez une fonction comme argument"""
#Paramètres de fonction
myFunc = myFunc or (lambda: self.dummy())
#Créer un bouton
self.button = tk.Button(text=myText, command=lambda: myFunc(self.combo.get()))
QuickBrowsing.py
import os
import subprocess
import sys
#Réinitialiser le chemin de recherche du module
#Rendre possible de démarrer en double-cliquant
sys.path.append(os.getenv("HOMEDRIVE") + os.getenv("HOMEPATH") + r"\PycharmProjects\CreateToolAndTest")
from Commons.JsonHandler import JsonHandler
from Commons.TkHandler_Combo_1 import TkHandler_Combo_1
import webbrowser
from time import sleep
# global
jsonHandler = None
siteList = None
tkHandler = None
siteName = None
def Main():
global jsonHandler
global siteList
global tkHandler
global siteName
#Acquisition d'objets
jsonHandler = JsonHandler(
r'C:\Users\dede2\PycharmProjects\CreateToolAndTest\Tool_Python/QuickBrowsing/webSiteDetails.json')
siteList = jsonHandler.getAll_OneNest()
#Affichage du formulaire
tkHandler = TkHandler_Combo_1('Navigation rapide', '640x200')
tkHandler.createFrame()
tkHandler.createLabel('Sélectionnez le site Web pour l'affichage par lots.')
tkHandler.createCombo(myValue=siteList)
tkHandler.createButton(myFunc=getSiteName)
tkHandler.mainLoop()
#Si le site n'est pas défini, il se termine normalement
#Si la page Web n'est pas enregistrée, elle se termine normalement
if siteName == None or not jsonHandler.getParam_TwoNest(siteName, 'OnlyOpenPage'):
exit(0)
#Ouvrez les sites Web dans l'ordre
subprocess.Popen("start chrome /new-tab www.google.com --new-window", shell=True)
sleep(1)
browser = webbrowser.get(r'"' + os.getenv(r'ProgramFiles(x86)') + \
r'\Google\Chrome\Application\chrome.exe" %s')
for url in jsonHandler.getParam_TwoNest(siteName, 'PageSet'):
browser.open(url)
def getSiteName(argName=''):
global tkHandler
global siteName
tkHandler.onClosing()
siteName = argName
if __name__ == '__main__':
Main()
siteList = jsonHandler.getAll_OneNest()
réduction
tkHandler.createCombo(myValue=siteList)
Obtenez uniquement l'en-tête du nom du site de json Faites-en un élément dans la liste déroulante.
tkHandler.createButton(myFunc=getSiteName)
réduction
def getSiteName(argName=''):
global tkHandler
global siteName
tkHandler.onClosing()
siteName = argName
Après avoir appuyé sur le bouton GUI, Je mets une valeur dans une variable globale et je la garde.
Après vérification, utilisez la méthode open_new du module Webbrowser. Il dit qu'il peut être ouvert dans une nouvelle fenêtre.
** Mais quand j'essaye de le déplacer, ça ne marche pas, ** ** S'ouvre comme un nouvel onglet dans la fenêtre d'origine. ** **
Apparemment, cela semble être une telle spécification. https://docs.python.org/ja/3/library/webbrowser.html
webbrowser.open_new(url) Si possible, ouvrez l'url dans une nouvelle fenêtre de votre navigateur par défaut, sinon ouvrez l'url dans une seule fenêtre de votre navigateur.
webbrowser.open_new_tab(url) Si possible, ouvrez l'url dans une nouvelle page ("onglet") dans le navigateur par défaut, sinon agissez comme open_new ().
Si chrome a été ouvert à l'origine, sous forme d'onglet de cette fenêtre Devrait ouvrir.
#Ouvrez les sites Web dans l'ordre
subprocess.Popen("start chrome /new-tab www.google.com --new-window", shell=True)
sleep(1)
browser = webbrowser.get(r'"' + os.getenv(r'ProgramFiles(x86)') + \
r'\Google\Chrome\Application\chrome.exe" %s')
for url in jsonHandler.getParam_TwoNest(siteName, 'PageSet'):
browser.open(url)
Ouvrez le navigateur Chrome dans une nouvelle fenêtre avec le sous-processus. Après avoir attendu une seconde J'ai décidé d'ouvrir toutes les pages du site sélectionné dans cette fenêtre à la fois.
Il peut être possible de l'implémenter de manière plus élégante.
Les derniers outils et code source sont disponibles ici. ↓ https://github.com/dede-20191130/CreateToolAndTest/tree/master/Tool_Python/QuickBrowsing
Veuillez commenter si vous avez des suppléments.
Une case à cocher a été implémentée dans l'interface graphique pour empêcher l'outil de quitter même après avoir appuyé sur le bouton de processus.
La classe enfant suivante a été créée par héritage. (Puisque la méthode d'enregistrement de chameau pour les fonctions et les variables ne semble pas être la norme python Changé pour utiliser la méthode d'enregistrement du serpent. )
TkHandler_Combo_1_CanKeep.py
import tkinter as tk
# Common parts in my GitHub
# https://github.com/dede-20191130/CreateToolAndTest
from Commons.TkHandler_Combo_1 import TkHandler_Combo_1
class TkHandler_Combo_1_CanKeep(TkHandler_Combo_1):
"""
Implémentation d'une case à cocher pour ne pas quitter l'outil même après avoir appuyé sur le bouton de processus
"""
def __init__(self, rootTitle='Titre', rootGeometry='640x480'):
super(TkHandler_Combo_1_CanKeep, self).__init__(rootTitle, rootGeometry)
self.keeping_check = None
self.bl = None
def create_keep_check(self, text='check box', is_initial=True):
self.bl = tk.BooleanVar(value=is_initial)
self.keeping_check = tk.Checkbutton(self.frame, text=text, variable=self.bl)
self.keeping_check.pack()
self.bl = tk.BooleanVar(value=is_initial)
self.keeping_check = tk.Checkbutton(self.frame, text=text, variable=self.bl)
BooleanVar est une variable de widget. Référence: https://suzutaka-programming.com/tkinter-variable/
Variables pouvant être spécifiées dans la variable -text et les options -variable.
Vous pouvez modifier dynamiquement la chaîne d'étiquette et obtenir la valeur saisie.
Réécrit comme suit.
QuickBrowsing.py
import os
import subprocess
import sys
#Réinitialiser le chemin de recherche du module
#Rendre possible de démarrer en double-cliquant
sys.path.append(os.getenv("HOMEDRIVE") + os.getenv("HOMEPATH") + r"\PycharmProjects\CreateToolAndTest")
# Common parts in my GitHub
# https://github.com/dede-20191130/CreateToolAndTest
from Commons.JsonHandler import JsonHandler
from Commons.TkHandler_Combo_1_CanKeep import TkHandler_Combo_1_CanKeep
import webbrowser
from time import sleep
# global
jsonHandler = None
siteList = None
tkHandler = None
siteName = None
def Main():
global jsonHandler
global siteList
global tkHandler
global siteName
#Acquisition d'objets
jsonHandler = JsonHandler(
r'C:/Users/UserName/MyFolder/Foo.json')
siteList = jsonHandler.getAll_OneNest()
#Affichage du formulaire
tkHandler = TkHandler_Combo_1_CanKeep('Navigation rapide', '640x200')
tkHandler.createFrame()
tkHandler.createLabel('Sélectionnez un site Web pour l'affichage par lots.')
tkHandler.createCombo(myValue=siteList)
tkHandler.create_keep_check('Vérifiez si cela ne se termine pas après l'exécution.')
tkHandler.createButton(myFunc=get_name_and_open)
tkHandler.mainLoop()
def get_name_and_open(argName=''):
global tkHandler
global siteName
if not tkHandler.bl.get():
tkHandler.onClosing()
siteName = argName
open_in_order()
def open_in_order():
global jsonHandler
global siteName
#Si le site n'est pas défini, il se termine normalement
#Si la page Web n'est pas enregistrée, elle se termine normalement
if siteName == None or not jsonHandler.getParam_TwoNest(siteName, 'OnlyOpenPage'):
exit(0)
#Ouvrez les sites Web dans l'ordre
subprocess.Popen("start chrome /new-tab www.google.com --new-window", shell=True)
sleep(1)
browser = webbrowser.get(r'"' + os.getenv(r'ProgramFiles(x86)') + \
r'\Google\Chrome\Application\chrome.exe" %s')
for url in jsonHandler.getParam_TwoNest(siteName, 'PageSet'):
browser.open(url)
if __name__ == '__main__':
Main()
if not tkHandler.bl.get():
tkHandler.onClosing()
Vous pouvez librement cocher et décocher les cases à cocher sur l'interface graphique. Si le bouton d'exécution est enfoncé lorsqu'il est activé, la méthode onclose n'est pas appelée.