Proyecto
This commit is contained in:
parent
650b20dda5
commit
27d83cc9ad
|
@ -23,21 +23,22 @@ class EconomyBitcoinChart:
|
|||
self.ax_bitcoin = self.figure.add_subplot(212) # Gráfico inferior
|
||||
|
||||
# Inicializar datos simulados
|
||||
self.economy_data = [random.randint(50, 100) for _ in range(10)] # Economía en meses
|
||||
self.bitcoin_data = [random.randint(20000, 60000) for _ in range(10)] # Bitcoin en días
|
||||
self.economy_data = [random.randint(50, 100) for _ in range(10)] # Índice económico en meses
|
||||
self.bitcoin_data = [random.randint(20000, 60000) for _ in range(10)] # Precio del Bitcoin en días
|
||||
|
||||
# Dibujar los gráficos iniciales
|
||||
self.update_economy_chart()
|
||||
self.update_bitcoin_chart()
|
||||
|
||||
# Embebiendo los gráficos en Tkinter
|
||||
# Embebiendo los gráficos en la interfaz de Tkinter
|
||||
self.canvas = FigureCanvasTkAgg(self.figure, master=self.parent)
|
||||
self.canvas.get_tk_widget().pack(fill="both", expand=True, padx=10, pady=10)
|
||||
|
||||
# Iniciar hilos para actualizar los gráficos
|
||||
# Iniciar hilos para actualizar los gráficos periódicamente
|
||||
threading.Thread(target=self.update_charts, daemon=True).start()
|
||||
|
||||
def update_economy_chart(self):
|
||||
"""Actualiza el gráfico de economía mundial."""
|
||||
"""Actualiza el gráfico de economía mundial con nuevos datos."""
|
||||
self.ax_economy.clear()
|
||||
self.ax_economy.plot(self.economy_data, marker="o", color="blue")
|
||||
self.ax_economy.set_title("Economía Mundial")
|
||||
|
@ -45,22 +46,22 @@ class EconomyBitcoinChart:
|
|||
self.ax_economy.grid(True)
|
||||
|
||||
def update_bitcoin_chart(self):
|
||||
"""Actualiza el gráfico de Bitcoin."""
|
||||
"""Actualiza el gráfico del precio de Bitcoin."""
|
||||
self.ax_bitcoin.clear()
|
||||
self.ax_bitcoin.plot(self.bitcoin_data, marker="o", color="green")
|
||||
self.ax_bitcoin.set_title("Precio de Bitcoin")
|
||||
self.ax_bitcoin.set_ylabel("Precio en USD")
|
||||
self.ax_bitcoin.set_xlabel("Días") # Etiqueta para los días
|
||||
self.ax_bitcoin.set_xlabel("Días") # Etiqueta del eje X
|
||||
self.ax_bitcoin.grid(True)
|
||||
|
||||
def update_charts(self):
|
||||
"""Actualiza ambos gráficos periódicamente."""
|
||||
"""Actualiza ambos gráficos con nuevos datos periódicamente."""
|
||||
while True:
|
||||
# Actualizar datos simulados
|
||||
self.economy_data = self.economy_data[1:] + [random.randint(50, 100)] # Economía en meses
|
||||
self.bitcoin_data = self.bitcoin_data[1:] + [random.randint(20000, 60000)] # Bitcoin en días
|
||||
# Generar nuevos datos simulados
|
||||
self.economy_data = self.economy_data[1:] + [random.randint(50, 100)]
|
||||
self.bitcoin_data = self.bitcoin_data[1:] + [random.randint(20000, 60000)]
|
||||
|
||||
# Actualizar gráficos
|
||||
# Redibujar gráficos con los nuevos datos
|
||||
self.update_economy_chart()
|
||||
self.update_bitcoin_chart()
|
||||
self.canvas.draw()
|
||||
|
|
|
@ -10,7 +10,7 @@ DOWNLOAD_FOLDER = "musicplayer"
|
|||
class MusicDownloader:
|
||||
def __init__(self, parent):
|
||||
"""
|
||||
Inicializa la interfaz para descargar música de YouTube en MP3.
|
||||
Inicializa la interfaz gráfica para descargar música de YouTube en formato MP3.
|
||||
"""
|
||||
self.parent = parent
|
||||
|
||||
|
@ -22,7 +22,7 @@ class MusicDownloader:
|
|||
title = tk.Label(self.parent, text="Descargar Música MP3", font=("Helvetica", 14, "bold"))
|
||||
title.pack(pady=10)
|
||||
|
||||
# Entrada para la URL
|
||||
# Campo de entrada para la URL de YouTube
|
||||
self.url_label = tk.Label(self.parent, text="URL de YouTube:")
|
||||
self.url_label.pack(pady=5)
|
||||
self.url_entry = tk.Entry(self.parent, width=50)
|
||||
|
@ -32,16 +32,16 @@ class MusicDownloader:
|
|||
self.download_button = tk.Button(self.parent, text="Descargar MP3", command=self.start_download, bg="lightblue")
|
||||
self.download_button.pack(pady=10)
|
||||
|
||||
# Barra de progreso
|
||||
# Barra de progreso de la descarga
|
||||
self.progress = ttk.Progressbar(self.parent, orient="horizontal", length=300, mode="determinate")
|
||||
self.progress.pack(pady=10)
|
||||
|
||||
# Etiqueta de estado
|
||||
# Etiqueta de estado para mostrar mensajes
|
||||
self.status_label = tk.Label(self.parent, text="", font=("Helvetica", 10))
|
||||
self.status_label.pack(pady=5)
|
||||
|
||||
def start_download(self):
|
||||
"""Inicia la descarga en un hilo separado."""
|
||||
"""Inicia la descarga en un hilo separado para no bloquear la interfaz."""
|
||||
url = self.url_entry.get()
|
||||
if not url:
|
||||
self.status_label.config(text="Por favor, ingrese una URL válida.", fg="red")
|
||||
|
@ -50,11 +50,12 @@ class MusicDownloader:
|
|||
threading.Thread(target=self.download_music, args=(url,), daemon=True).start()
|
||||
|
||||
def download_music(self, url):
|
||||
"""Descarga el audio de YouTube en MP3 usando yt-dlp."""
|
||||
"""Descarga el audio de YouTube en formato MP3 usando `yt-dlp`."""
|
||||
try:
|
||||
self.status_label.config(text="Descargando...", fg="blue")
|
||||
output_template = os.path.join(DOWNLOAD_FOLDER, "%(title)s.%(ext)s")
|
||||
|
||||
# Opciones para descargar solo el audio y convertirlo a MP3
|
||||
ydl_opts = {
|
||||
'format': 'bestaudio/best',
|
||||
'outtmpl': output_template,
|
||||
|
@ -71,6 +72,7 @@ class MusicDownloader:
|
|||
self.status_label.config(text="¡Descarga completada!", fg="green")
|
||||
except Exception as e:
|
||||
self.status_label.config(text=f"Error: {str(e)}", fg="red")
|
||||
|
||||
def update_progress(self, stream, chunk, bytes_remaining):
|
||||
"""Actualiza la barra de progreso durante la descarga."""
|
||||
total_size = stream.filesize
|
||||
|
|
|
@ -4,33 +4,32 @@ import threading
|
|||
import mysql.connector
|
||||
from mysql.connector import Error
|
||||
|
||||
|
||||
class SQLQueryExecutor:
|
||||
def __init__(self, parent):
|
||||
"""
|
||||
Clase para ejecutar consultas SQL en una base de datos MySQL.
|
||||
Clase que permite ejecutar consultas SQL en una base de datos MySQL.
|
||||
|
||||
Args:
|
||||
parent (tk.Frame): Frame donde se colocarán los widgets.
|
||||
parent (tk.Frame): Frame donde se colocarán los widgets de la interfaz gráfica.
|
||||
"""
|
||||
self.parent = parent
|
||||
|
||||
# Campos para ingresar información de conexión
|
||||
# Frame para ingresar los datos de conexión a la base de datos
|
||||
self.db_info_frame = tk.Frame(self.parent)
|
||||
self.db_info_frame.pack(pady=10, padx=10, fill="x")
|
||||
|
||||
tk.Label(self.db_info_frame, text="Host:").grid(row=0, column=0, sticky="w")
|
||||
self.host_entry = tk.Entry(self.db_info_frame)
|
||||
self.host_entry.insert(0, "localhost")
|
||||
self.host_entry.insert(0, "localhost") # Valor por defecto
|
||||
self.host_entry.grid(row=0, column=1)
|
||||
|
||||
tk.Label(self.db_info_frame, text="Usuario:").grid(row=1, column=0, sticky="w")
|
||||
self.user_entry = tk.Entry(self.db_info_frame)
|
||||
self.user_entry.insert(0, "root")
|
||||
self.user_entry.insert(0, "root") # Usuario por defecto
|
||||
self.user_entry.grid(row=1, column=1)
|
||||
|
||||
tk.Label(self.db_info_frame, text="Contraseña:").grid(row=2, column=0, sticky="w")
|
||||
self.password_entry = tk.Entry(self.db_info_frame, show="*")
|
||||
self.password_entry = tk.Entry(self.db_info_frame, show="*") # Campo oculto
|
||||
self.password_entry.grid(row=2, column=1)
|
||||
|
||||
tk.Label(self.db_info_frame, text="Base de datos:").grid(row=3, column=0, sticky="w")
|
||||
|
@ -41,7 +40,7 @@ class SQLQueryExecutor:
|
|||
self.connect_button = tk.Button(self.db_info_frame, text="Conectar", command=self.connect_to_database)
|
||||
self.connect_button.grid(row=4, column=0, columnspan=2, pady=5)
|
||||
|
||||
# Área para ingresar consultas SQL
|
||||
# Área para escribir la consulta SQL
|
||||
self.query_frame = tk.Frame(self.parent)
|
||||
self.query_frame.pack(pady=10, padx=10, fill="both", expand=True)
|
||||
|
||||
|
@ -49,11 +48,11 @@ class SQLQueryExecutor:
|
|||
self.query_text = tk.Text(self.query_frame, height=10)
|
||||
self.query_text.pack(fill="both", expand=True)
|
||||
|
||||
# Botón para ejecutar consultas
|
||||
# Botón para ejecutar la consulta
|
||||
self.execute_button = tk.Button(self.query_frame, text="Ejecutar", command=self.execute_query)
|
||||
self.execute_button.pack(pady=5)
|
||||
|
||||
# Área para mostrar resultados
|
||||
# Área para mostrar los resultados
|
||||
self.result_frame = tk.Frame(self.parent)
|
||||
self.result_frame.pack(pady=10, padx=10, fill="both", expand=True)
|
||||
|
||||
|
@ -62,7 +61,7 @@ class SQLQueryExecutor:
|
|||
self.result_text.pack(fill="both", expand=True)
|
||||
|
||||
def connect_to_database(self):
|
||||
"""Conecta a la base de datos utilizando los datos proporcionados."""
|
||||
"""Conecta a la base de datos MySQL utilizando los datos ingresados por el usuario."""
|
||||
self.host = self.host_entry.get()
|
||||
self.user = self.user_entry.get()
|
||||
self.password = self.password_entry.get()
|
||||
|
@ -81,7 +80,7 @@ class SQLQueryExecutor:
|
|||
messagebox.showerror("Error de Conexión", str(e))
|
||||
|
||||
def execute_query(self):
|
||||
"""Ejecuta la consulta SQL en un hilo separado."""
|
||||
"""Ejecuta la consulta SQL en un hilo separado para evitar bloquear la interfaz."""
|
||||
query = self.query_text.get("1.0", tk.END).strip()
|
||||
if not query:
|
||||
messagebox.showwarning("Consulta Vacía", "Por favor, ingrese una consulta SQL.")
|
||||
|
@ -90,7 +89,7 @@ class SQLQueryExecutor:
|
|||
threading.Thread(target=self.run_query, args=(query,), daemon=True).start()
|
||||
|
||||
def run_query(self, query):
|
||||
"""Ejecuta la consulta y muestra los resultados."""
|
||||
"""Ejecuta la consulta en la base de datos y muestra los resultados."""
|
||||
try:
|
||||
cursor = self.connection.cursor()
|
||||
cursor.execute(query)
|
||||
|
|
|
@ -4,7 +4,6 @@ from tkinter import messagebox
|
|||
import threading
|
||||
import random
|
||||
|
||||
|
||||
class TicTacToe:
|
||||
def __init__(self, parent):
|
||||
"""
|
||||
|
@ -14,19 +13,19 @@ class TicTacToe:
|
|||
parent (tk.Frame): Frame donde se colocará el juego.
|
||||
"""
|
||||
self.parent = parent
|
||||
self.board = [""] * 9 # Tablero de 3x3 representado como una lista
|
||||
self.current_player = "X" # Jugador inicial
|
||||
self.board = [""] * 9 # Representación del tablero 3x3
|
||||
self.current_player = "X" # Jugador que inicia la partida
|
||||
self.vs_computer = False # Modo jugador vs máquina
|
||||
|
||||
# Etiqueta para el título
|
||||
# Título del juego
|
||||
title = tk.Label(self.parent, text="Tic Tac Toe", font=("Helvetica", 16, "bold"))
|
||||
title.pack(pady=10)
|
||||
|
||||
# Botón para alternar entre modos
|
||||
# Botón para alternar entre modos de juego
|
||||
self.mode_button = tk.Button(self.parent, text="Modo: Jugador vs Jugador", command=self.toggle_mode)
|
||||
self.mode_button.pack(pady=5)
|
||||
|
||||
# Crear el tablero
|
||||
# Crear la cuadrícula del tablero
|
||||
self.buttons = []
|
||||
self.board_frame = tk.Frame(self.parent)
|
||||
self.board_frame.pack()
|
||||
|
@ -38,12 +37,12 @@ class TicTacToe:
|
|||
font=("Helvetica", 20),
|
||||
width=5,
|
||||
height=2,
|
||||
command=self.create_button_command(i) # Aquí usamos la función auxiliar
|
||||
command=self.create_button_command(i)
|
||||
)
|
||||
button.grid(row=i // 3, column=i % 3)
|
||||
self.buttons.append(button)
|
||||
|
||||
# Etiqueta para el estado del juego
|
||||
# Mensaje que indica el turno del jugador
|
||||
self.status_label = tk.Label(self.parent, text="Turno: X", font=("Helvetica", 12))
|
||||
self.status_label.pack(pady=5)
|
||||
|
||||
|
@ -55,7 +54,7 @@ class TicTacToe:
|
|||
self.reset_game()
|
||||
|
||||
def reset_game(self):
|
||||
"""Reinicia el tablero y el estado del juego."""
|
||||
"""Reinicia el juego a su estado inicial."""
|
||||
self.board = [""] * 9
|
||||
self.current_player = "X"
|
||||
for button in self.buttons:
|
||||
|
@ -63,12 +62,11 @@ class TicTacToe:
|
|||
self.status_label.config(text="Turno: X")
|
||||
|
||||
def make_move(self, index):
|
||||
"""Realiza un movimiento en el tablero."""
|
||||
"""Registra un movimiento y actualiza el tablero."""
|
||||
if self.board[index] == "":
|
||||
self.board[index] = self.current_player
|
||||
self.buttons[index].config(text=self.current_player)
|
||||
|
||||
# Verificar si hay un ganador
|
||||
winner = self.check_winner()
|
||||
if winner:
|
||||
self.end_game(f"¡Ganador: {winner}!")
|
||||
|
@ -77,28 +75,11 @@ class TicTacToe:
|
|||
self.end_game("¡Empate!")
|
||||
return
|
||||
|
||||
# Cambiar de jugador
|
||||
self.current_player = "O" if self.current_player == "X" else "X"
|
||||
self.status_label.config(text=f"Turno: {self.current_player}")
|
||||
|
||||
# Si está en modo Jugador vs Máquina y es el turno de la máquina
|
||||
if self.vs_computer and self.current_player == "O":
|
||||
threading.Thread(target=self.computer_move).start()
|
||||
|
||||
def computer_move(self):
|
||||
"""Simula el movimiento de la máquina."""
|
||||
self.status_label.config(text="Turno: Máquina (O)")
|
||||
available_moves = [i for i, v in enumerate(self.board) if v == ""]
|
||||
move = random.choice(available_moves)
|
||||
|
||||
def delayed_move():
|
||||
time.sleep(1) # Simular el tiempo de "pensar"
|
||||
self.make_move(move)
|
||||
|
||||
threading.Thread(target=delayed_move).start()
|
||||
|
||||
def check_winner(self):
|
||||
"""Verifica si hay un ganador."""
|
||||
"""Verifica si hay un ganador en el juego."""
|
||||
winning_combinations = [
|
||||
(0, 1, 2), (3, 4, 5), (6, 7, 8), # Filas
|
||||
(0, 3, 6), (1, 4, 7), (2, 5, 8), # Columnas
|
||||
|
@ -108,16 +89,3 @@ class TicTacToe:
|
|||
if self.board[a] == self.board[b] == self.board[c] and self.board[a] != "":
|
||||
return self.board[a]
|
||||
return None
|
||||
|
||||
def end_game(self, message):
|
||||
"""Finaliza el juego mostrando un mensaje."""
|
||||
messagebox.showinfo("Fin del Juego", message)
|
||||
self.reset_game()
|
||||
|
||||
def create_button_command(self, index):
|
||||
"""Crea un comando para un botón con un índice específico."""
|
||||
|
||||
def command():
|
||||
self.make_move(index)
|
||||
|
||||
return command
|
|
@ -9,52 +9,59 @@ from tkinter import messagebox
|
|||
class WebScraperToDB:
|
||||
def __init__(self, parent):
|
||||
"""
|
||||
Inicializa el widget de scraping con integración a base de datos.
|
||||
Inicializa la interfaz gráfica para scraping web con integración a base de datos.
|
||||
|
||||
Args:
|
||||
parent (tk.Frame): Contenedor en el que se mostrará la interfaz gráfica.
|
||||
"""
|
||||
self.parent = parent
|
||||
self.scraping_thread = None
|
||||
self.stop_event = threading.Event()
|
||||
self.scraping_thread = None # Hilo que ejecutará el scraping
|
||||
self.stop_event = threading.Event() # Evento para detener el scraping
|
||||
|
||||
# Crear campos de conexión para la base de datos
|
||||
# Crear la sección de conexión a la base de datos
|
||||
db_frame = tk.Frame(self.parent)
|
||||
db_frame.pack(pady=5)
|
||||
|
||||
# Campos de entrada para la conexión a MySQL
|
||||
tk.Label(db_frame, text="Host:").grid(row=0, column=0)
|
||||
self.host_entry = tk.Entry(db_frame)
|
||||
self.host_entry.insert(0, "localhost")
|
||||
self.host_entry.insert(0, "localhost") # Valor predeterminado
|
||||
self.host_entry.grid(row=0, column=1)
|
||||
|
||||
tk.Label(db_frame, text="Usuario:").grid(row=1, column=0)
|
||||
self.user_entry = tk.Entry(db_frame)
|
||||
self.user_entry.insert(0, "root")
|
||||
self.user_entry.insert(0, "root") # Usuario predeterminado
|
||||
self.user_entry.grid(row=1, column=1)
|
||||
|
||||
tk.Label(db_frame, text="Contraseña:").grid(row=2, column=0)
|
||||
self.password_entry = tk.Entry(db_frame, show="*")
|
||||
self.password_entry = tk.Entry(db_frame, show="*") # Campo oculto para seguridad
|
||||
self.password_entry.grid(row=2, column=1)
|
||||
|
||||
tk.Label(db_frame, text="Nombre BD:").grid(row=3, column=0)
|
||||
self.database_entry = tk.Entry(db_frame)
|
||||
self.database_entry.insert(0, "scraping_db")
|
||||
self.database_entry.insert(0, "scraping_db") # Base de datos predeterminada
|
||||
self.database_entry.grid(row=3, column=1)
|
||||
|
||||
# Botón para crear la base de datos
|
||||
tk.Button(db_frame, text="Crear Base de Datos", command=self.create_database).grid(row=4, column=0, columnspan=2, pady=5)
|
||||
|
||||
# Área para URL y botones de control
|
||||
# Sección de controles para scraping
|
||||
control_frame = tk.Frame(self.parent)
|
||||
control_frame.pack(pady=5)
|
||||
|
||||
# Campo de entrada para la URL a scrape
|
||||
tk.Label(control_frame, text="URL para Scraping:").grid(row=0, column=0)
|
||||
self.url_entry = tk.Entry(control_frame, width=50)
|
||||
self.url_entry.insert(0, "https://quotes.toscrape.com/")
|
||||
self.url_entry.insert(0, "https://quotes.toscrape.com/") # URL de prueba
|
||||
self.url_entry.grid(row=0, column=1)
|
||||
|
||||
# Campo para Selector HTML
|
||||
# Campo para ingresar el selector HTML
|
||||
tk.Label(control_frame, text="Selector HTML:").grid(row=2, column=0)
|
||||
self.selector_entry = tk.Entry(control_frame, width=50)
|
||||
self.selector_entry.insert(0, "h1") # Valor predeterminado
|
||||
self.selector_entry.insert(0, "h1") # Selector predeterminado
|
||||
self.selector_entry.grid(row=2, column=1)
|
||||
|
||||
# Botones de control
|
||||
self.start_button = tk.Button(control_frame, text="Iniciar Scraping", command=self.start_scraping)
|
||||
self.start_button.grid(row=1, column=0, pady=5)
|
||||
|
||||
|
@ -64,7 +71,7 @@ class WebScraperToDB:
|
|||
self.reset_button = tk.Button(control_frame, text="Resetear Scraping", command=self.reset_database)
|
||||
self.reset_button.grid(row=1, column=2, pady=5)
|
||||
|
||||
# Área para mostrar el estado
|
||||
# Etiqueta para mostrar el estado del scraping
|
||||
self.status_label = tk.Label(self.parent, text="Estado: Inactivo", fg="red")
|
||||
self.status_label.pack(pady=5)
|
||||
|
||||
|
@ -78,7 +85,7 @@ class WebScraperToDB:
|
|||
self.scraped_data_text.pack(fill="both", expand=True)
|
||||
|
||||
def create_database(self):
|
||||
"""Crea la base de datos y la tabla para almacenar datos de scraping."""
|
||||
"""Crea la base de datos y la tabla para almacenar los datos de scraping."""
|
||||
try:
|
||||
connection = mysql.connector.connect(
|
||||
host=self.host_entry.get(),
|
||||
|
@ -119,9 +126,7 @@ class WebScraperToDB:
|
|||
selector = self.selector_entry.get()
|
||||
|
||||
try:
|
||||
headers = {
|
||||
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36"
|
||||
}
|
||||
headers = {"User-Agent": "Mozilla/5.0"}
|
||||
connection = mysql.connector.connect(
|
||||
host=self.host_entry.get(),
|
||||
user=self.user_entry.get(),
|
||||
|
@ -134,7 +139,7 @@ class WebScraperToDB:
|
|||
response = requests.get(url, headers=headers)
|
||||
soup = BeautifulSoup(response.text, "html.parser")
|
||||
|
||||
# Busca elementos según el selector ingresado por el usuario
|
||||
# Busca elementos en la página usando el selector proporcionado
|
||||
elements = soup.select(selector)
|
||||
if not elements:
|
||||
self.status_label.config(text="Estado: Sin datos encontrados.", fg="orange")
|
||||
|
@ -143,9 +148,9 @@ class WebScraperToDB:
|
|||
|
||||
for element in elements:
|
||||
title_text = element.get_text(strip=True)
|
||||
link = element.get("href", "Sin enlace") # Asegúrate de que el selector apunte a elementos <a>
|
||||
link = element.get("href", "Sin enlace") # Extrae el enlace si está disponible
|
||||
|
||||
# Insertar en la base de datos
|
||||
# Insertar datos en la base de datos
|
||||
cursor.execute("INSERT INTO scraped_data (title, link) VALUES (%s, %s)", (title_text, link))
|
||||
connection.commit()
|
||||
|
||||
|
@ -157,8 +162,7 @@ class WebScraperToDB:
|
|||
|
||||
self.status_label.config(text=f"Estado: Scrapeando {title_text}...", fg="green")
|
||||
|
||||
# Pausa entre iteraciones
|
||||
time.sleep(5)
|
||||
time.sleep(5) # Pausa entre iteraciones
|
||||
|
||||
connection.close()
|
||||
self.status_label.config(text="Estado: Inactivo", fg="red")
|
||||
|
@ -173,7 +177,7 @@ class WebScraperToDB:
|
|||
self.stop_button.config(state="disabled")
|
||||
|
||||
def reset_database(self):
|
||||
"""Elimina todos los datos de la tabla."""
|
||||
"""Elimina todos los datos de la tabla scraped_data."""
|
||||
try:
|
||||
connection = mysql.connector.connect(
|
||||
host=self.host_entry.get(),
|
||||
|
|
Loading…
Reference in New Issue