I need your help to solve this problem, I want to refresh a QlistWidget in pyqt4 when I add a new register from another QMainWindow not in the principal, i tried with "repaint()" but it doesn´t work, to understand it better I post the code
This is the main window where I added all items from a DB
class Psicologo(QMainWindow):
def __init__(self, parent=None):
super(Psicologo, self).__init__(parent)
uic.loadUi('inicio.ui', self)
self.button_volver.clicked.connect(self.regresar)
self.button_nvo_psicologo.clicked.connect(self.nuevoPsicologo)
query = "SELECT * FROM user"
cursor, conexion = CreateConexion()
cursor.execute(query)
registro = cursor.fetchall()
for i in registro:
self.lista_psicologos.addItem(i[1]+" "+i[2]+" "+i[3])
def regresar(self):
self.parent().show()
self.close()
def nuevoPsicologo(self):
self.hide()
nuevo_form = AltaPsico(self)
nuevo_form.show()
And here is the other window where I create a new register
class AltaPsico(QMainWindow):
def __init__(self, parent=None):
super(AltaPsico, self).__init__(parent)
uic.loadUi('alta_paciente.ui', self)
self.combo_sexo.hide()
self.label_12.hide()
self.text_comentario.hide()
self.label_14.hide()
self.line_correo_2.hide()
self.label_13.hide()
self.button_volver.clicked.connect(self.regresar)
self.button_guardar.clicked.connect(self.guardar)
self.button_eliminar.hide()
def guardar(self):
nombre = self.line_nombre.text()
app = self.line_app.text()
apm = self.line_apm.text()
domicilio = self.line_domicilio.text()
edad = self.line_edad.text()
telefono = self.line_telefono.text()
especialidad = self.line_especialidad.text()
correo = self.line_correo.text()
usuario = self.line_usuario.text()
password = self.line_password.text()
pass2 = self.line_password_2.text()
if password == pass2:
if edad.isdigit():
if validate_email(correo):
if telefono.isdigit():
query = "INSERT INTO user(idUser, Nombre, ApPaterno, ApMaterno, Domicilio, Edad, Telefono, Especialidad, Correo, Usuario, Password, Tipo) VALUES (0,'"+nombre+"','"+app+"', '"+apm+"', '"+domicilio+"', '"+edad+"', '"+telefono+"', '"+especialidad+"', '"+correo+"', '"+usuario+"', '"+password+"', 2);"
print (query)
cursor, conexion = CreateConexion()
cursor.execute(query)
msgBoxCancel = QtGui.QMessageBox( self )
msgBoxCancel.setIcon( QtGui.QMessageBox.Information )
msgBoxCancel.setText( "Usuario registrado con exito" )
msgBoxCancel.addButton( QtGui.QMessageBox.Ok )
msgBoxCancel.exec_()
conexion.commit()
conexion.close()
self.parent().show()
self.QMainWindow.update()
self.close()
else:
msgBoxCancel = QtGui.QMessageBox( self )
msgBoxCancel.setIcon( QtGui.QMessageBox.Information )
msgBoxCancel.setText( "¡Telefono invalido, ingrese telefono valido!" )
msgBoxCancel.addButton( QtGui.QMessageBox.Ok )
msgBoxCancel.exec_()
else:
msgBoxCancel = QtGui.QMessageBox( self )
msgBoxCancel.setIcon( QtGui.QMessageBox.Information )
msgBoxCancel.setText( "¡Correo invalido, ingrese correo valido!" )
msgBoxCancel.addButton( QtGui.QMessageBox.Ok )
msgBoxCancel.exec_()
else:
msgBoxCancel = QtGui.QMessageBox( self )
msgBoxCancel.setIcon( QtGui.QMessageBox.Information )
msgBoxCancel.setText( "¡Ingrese una edad valida!" )
msgBoxCancel.addButton( QtGui.QMessageBox.Ok )
msgBoxCancel.exec_()
else:
msgBoxCancel = QtGui.QMessageBox( self )
msgBoxCancel.setIcon( QtGui.QMessageBox.Information )
msgBoxCancel.setText( "¡La contraseña no coincide, intentelo de nuevo!" )
msgBoxCancel.addButton( QtGui.QMessageBox.Ok )
msgBoxCancel.exec_()
def regresar(self):
self.parent().repaint()
self.parent().show()
self.close()
When the register ends succesfully this window closes automatically but when the principal shows again the listWidget shows the same registers at the begin.
I hope this community can help me, i´ve been searching about this topic but i can´t find anything.
If the database is modified, the GUI is not notified so the data must be requested again:
class Psicologo(QMainWindow):
def __init__(self, parent=None):
super(Psicologo, self).__init__(parent)
uic.loadUi('inicio.ui', self)
self.button_volver.clicked.connect(self.regresar)
self.button_nvo_psicologo.clicked.connect(self.nuevoPsicologo)
self.load_from_db()
def load_from_db(self):
self.lista_psicologos.clear()
query = "SELECT * FROM user"
cursor, conexion = CreateConexion()
cursor.execute(query)
registro = cursor.fetchall()
for i in registro:
self.lista_psicologos.addItem("{} {} {}".format(i[1], i[2], i[3]))
def regresar(self):
self.parent().show()
self.close()
def nuevoPsicologo(self):
self.hide()
nuevo_form = AltaPsico(self)
nuevo_form.show()
def guardar(self):
# ...
conexion.commit()
conexion.close()
self.parent().show()
self.parent().load_from_db()
Related
from discord.ext import commands
import youtube_dl
import music
bot = commands.Bot(command_prefix="?", intents=discord.Intents.all())
bot.remove_command('help')
class music(commands.Bot):
def __init__(self, client):
self.client = client
# all the music related stuff
self.is_playing = False
# 2d array containing [song, channel]
self.music_queue = []
self.YDL_OPTIONS = {'format': 'bestaudio', 'noplaylist': 'True'}
self.FFMPEG_OPTIONS = {
'before_options': '-reconnect 1 -reconnect_streamed 1 -reconnect_delay_max 5', 'options': '-vn'}
self.vc = ""
# searching the item on youtube
def search_yt(self, item):
with youtube_dl(self.YDL_OPTIONS) as ydl:
try:
info = ydl.extract_info("ytsearch:%s" %
item, download=False)['entries'][0]
except Exception:
return False
return {'source': info['formats'][0]['url'], 'title': info['title']}
def play_next(self):
if len(self.music_queue) > 0:
self.is_playing = True
# get the first url
m_url = self.music_queue[0][0]['source']
# remove the first element as you are currently playing it
self.music_queue.pop(0)
self.vc.play(discord.FFmpegPCMAudio(
m_url, **self.FFMPEG_OPTIONS), after=lambda e: self.play_next())
else:
self.is_playing = False
# infinite loop checking
async def play_music(self):
if len(self.music_queue) > 0:
self.is_playing = True
m_url = self.music_queue[0][0]['source']
# try to connect to voice channel if you are not already connected
if self.vc == "" or not self.vc.is_connected() or self.vc == None:
self.vc = await self.music_queue[0][1].connect()
else:
await self.vc.move_to(self.music_queue[0][1])
print(self.music_queue)
# remove the first element as you are currently playing it
self.music_queue.pop(0)
self.vc.play(discord.FFmpegPCMAudio(
m_url, **self.FFMPEG_OPTIONS), after=lambda e: self.play_next())
else:
self.is_playing = False
await self.vc.disconnect()
#bot.command(name="help", alisases=['ajuda'], help="Comando de ajuda")
async def help(self, ctx):
helptxt = ''
for command in self.client.commands:
helptxt += f'**{command}** - {command.help}\n'
embedhelp = discord.Embed(
colour=1646116, # grey
title=f'Comandos do {self.client.user.name}',
description=helptxt + \
'\n[Crie seu próprio Bot de Música](https://youtu.be/YGx0xNHzjgE)'
)
embedhelp.set_thumbnail(url=self.client.user.avatar_url)
await ctx.send(embed=embedhelp)
#bot.command(name="play", help="Toca uma música do YouTube", aliases=['p', 'tocar'])
async def p(self, ctx, *args):
query = " ".join(args)
try:
voice_channel = ctx.author.voice.channel
except:
# if voice_channel is None:
# you need to be connected so that the bot knows where to go
embedvc = discord.Embed(
colour=1646116, # grey
description='Para tocar uma música, primeiro se conecte a um canal de voz.'
)
await ctx.send(embed=embedvc)
return
else:
song = self.search_yt(query)
if type(song) == type(True):
embedvc = discord.Embed(
colour=12255232, # red
description='Algo deu errado! Tente mudar ou configurar a playlist/vídeo ou escrever o nome dele novamente!'
)
await ctx.send(embed=embedvc)
else:
embedvc = discord.Embed(
colour=32768, # green
description=f"Você adicionou a música **{song['title']}** à fila!\n\n[Crie seu próprio Bot de Música](https://youtu.be/YGx0xNHzjgE)"
)
await ctx.send(embed=embedvc)
self.music_queue.append([song, voice_channel])
if self.is_playing == False:
await self.play_music()
#bot.command(name="queue", help="Mostra as atuais músicas da fila.", aliases=['q', 'fila'])
async def q(self, ctx):
retval = ""
for i in range(0, len(self.music_queue)):
retval += f'**{i+1} - **' + self.music_queue[i][0]['title'] + "\n"
print(retval)
if retval != "":
embedvc = discord.Embed(
colour=12255232,
description=f"{retval}"
)
await ctx.send(embed=embedvc)
else:
embedvc = discord.Embed(
colour=1646116,
description='Não existe músicas na fila no momento.'
)
await ctx.send(embed=embedvc)
#bot.command(name="skip", help="Pula a atual música que está tocando.", aliases=['pular'])
async def skip(self, ctx):
if self.vc != "" and self.vc:
self.vc.stop()
# try to play next in the queue if it exists
await self.play_music()
embedvc = discord.Embed(
colour=1646116, # ggrey
description=f"Você pulou a música."
)
await ctx.send(embed=embedvc)
#skip.error # Erros para kick
async def skip_error(self, ctx, error):
if isinstance(error, commands.MissingPermissions):
embedvc = discord.Embed(
colour=12255232,
description=f"Você precisa da permissão **Gerenciar canais** para pular músicas."
)
await ctx.send(embed=embedvc)
else:
raise error
def setup(client):
client.add_cog(music(client))
bot.run('TOKEN')
I'm trying to create a bot for discord and this error is occurring
[discord.ext.commands.errors.CommandInvokeError: Command raised an exception: TypeError: music.help() missing 1 required positional argument: 'ctx'],
this is my last hope.
I just can't make it work
(sorry for bad english, I'm using google translator)
I am trying to create a calendar app in python.As for now I have manage to create the Gtk.window, a Gtk.Notebook with two pages (page1 month calendar, page 2 week calendar) added to the Gtk.window.I have used Gtk.Calendar for month and from signal 'day-selected' I used a function to get_date().Also I used a Gtk.TextView with Gtk.TextBuffer to input text (as a note).
First question : how to connect the date with the input text and store it in a list or dictionary so i can save it later to a file.
Second:I have activate details with self.calendar.set_property("show-details", True) and defined a function self.calendar.set_detail_func(self.cal_entry) for details.
def cal_entry(self, calendar, year, month, date):
if self.textbuffer is not None:
self.calendar.mark_day(self.day)
How to mark the days with notes(text in Gtk.TextBuffer) because the above function does not work correctly.
Below is a snippet of the code:
class Window(Gtk.ApplicationWindow):
def __init__(self, app):
super(Window, self).__init__(title="Live Calendar", application=app)
self.set_default_size(-1, 400)
self.set_resizable(False)
self.set_border_width(10)
self.create_notebook()
self.entry()
self.refresh_icon()
def refresh_icon(self):
#refreshing the icon of the app
print(get_filename())
subject_lines = read_file(subject)
index = [i for i in range(len(subject_lines)) \
if subject_lines[i].startswith("Icon=")][0]
subject_lines[index] = "Icon=" + get_filename() + "\n"
write_file(subject, subject_lines)
self.set_icon_from_file(get_filename())
timer = threading.Timer(60, self.refresh_icon)
timer.start()
def create_notebook(self):
# Open Buttton
self.openbutton = Gtk.Button("Open")
self.openbutton.set_tooltip_text("Open Notes")
self.openbutton.connect("clicked", self.on_open_clicked)
# Save Button
self.savebutton = Gtk.Button("Save")
self.savebutton.set_tooltip_text("Save Notes")
self.savebutton.connect("clicked", self.on_save_clicked)
# Header
self.header = Gtk.HeaderBar(title="Live Calendar")
self.header.set_property("show_close_button", True)
self.header.pack_start(self.openbutton)
self.header.pack_start(self.savebutton)
self.set_titlebar(self.header)
#page1 month calendar
self.page1 = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=0)
self.calendar = Gtk.Calendar()
self.calendar.set_property("show-week-numbers", True)
self.calendar.set_detail_height_rows(2)
self.calendar.set_detail_width_chars(2)
self.calendar.set_property("show-details", True)
self.calendar.set_detail_func(self.cal_entry)
self.__connect_signals()
self.page1.add(self.calendar)
#note taking
self.sw = Gtk.ScrolledWindow()
self.sw.set_hexpand(True)
self.sw.set_vexpand(True)
self.textview = Gtk.TextView()
self.textview.set_editable(True)
self.textview.set_wrap_mode(Gtk.WrapMode.WORD_CHAR)
self.textbuffer = self.textview.get_buffer()
self.sw.add(self.textview)
self.page1.pack_start(self.sw, True, True, 0)
#page2 week calendar
......a lot of code.......
#create notebook
self.notebook = Gtk.Notebook()
self.notebook.set_tab_pos(0)
self.notebook.append_page(self.page1, Gtk.Label('Month'))
self.notebook.append_page(self.page2, Gtk.Label('Week'))
self.add(self.notebook)
def __connect_signals(self):
self.day_selected_handle = self.calendar.connect('day-selected', self.entry)
def entry(self, *args):
self.page1.remove(self.label)
self.year, self.month, self.day = self.calendar.get_date()
self.month = self.month + 1
self.entrydate = datetime.date(self.year, self.month, self.day)
self.notedate = self.entrydate.strftime("%d/%m/%y")
self.text = self.entrydate.strftime("%d/%m/%y write your notes here...")
self.label = Gtk.Label(self.text)
self.page1.pack_start(self.label, False, False, 0)
self.show_all()
def cal_entry(self, calendar, year, month, date):
if self.textbuffer is not None:
self.calendar.mark_day(self.day)
#save into file
def on_save_clicked(self, widget):
dialog = Gtk.FileChooserDialog("Save file", self,
Gtk.FileChooserAction.SAVE,
(Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL,
Gtk.STOCK_SAVE, Gtk.ResponseType.OK))
response = dialog.run()
if response == Gtk.ResponseType.OK:
save_file = dialog.get_filename()
start_iter = self.textbuffer.get_start_iter()
end_iter = self.textbuffer.get_end_iter()
text = self.textbuffer.get_text(start_iter, end_iter, True)
with open(save_file, 'w') as f:
f.write(text)
elif response == Gtk.ResponseType.CANCEL:
dialog.destroy()
dialog.destroy()
# open and read the file
def on_open_clicked(self, widget):
dialog = Gtk.FileChooserDialog("Please choose a file", self,
Gtk.FileChooserAction.OPEN,
(Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL,
Gtk.STOCK_OPEN, Gtk.ResponseType.OK))
filter_text = Gtk.FileFilter()
filter_text.set_name("Text files")
filter_text.add_mime_type("text/plain")
dialog.add_filter(filter_text)
response = dialog.run()
if response == Gtk.ResponseType.OK:
selected_file = dialog.get_filename()
with open(selected_file, 'r') as f:
data = f.read()
self.textbuffer.set_text(data)
elif response == Gtk.ResponseType.CANCEL:
dialog.destroy()
dialog.destroy()
def quitApp(self, par):
app.quit()
class Application(Gtk.Application):
def __init__(self):
super(Application, self).__init__()
def do_activate(self):
self.win = Window(self)
self.win.show_all()
def do_startup(self):
Gtk.Application.do_startup(self)
app = Application()
app.run(sys.argv)
Any help will be appriciated.
Thanks in advance
For the first question: Depends, but probably a dictionary indexed by a triple for y/m/d
d = dict()
d[(2019, 10, 1)] = "your notes..."
Second question: The way details work is that cal_entry(self, calendar, year, month, day) must return a string to be displayed below the day, in the calendar. So you have to get the text from the dictionary above. You can do that with:
def cal_entry(self, calendar, year, month, day):
self.calendar.mark_day(day)
return dict.get((year, month, day))
Maybe this sample code can help:
#!/usr/bin/env python3
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk
class NotePopover(Gtk.Popover):
def __init__(self, app):
Gtk.Popover.__init__(self)
self.set_size_request(200, 300)
grid = Gtk.Grid()
grid.set_orientation(Gtk.Orientation.VERTICAL)
scrolled_window = Gtk.ScrolledWindow()
self.text_view = Gtk.TextView()
scrolled_window.add(self.text_view)
grid.add(scrolled_window)
button = Gtk.Button(label='Add')
grid.add(button)
grid.show_all()
self.add(grid)
scrolled_window.set_vexpand(True)
scrolled_window.set_hexpand(True)
button.connect('clicked', self.on_button_clicked)
self.app = app
def do_popup(self):
self.popup()
def on_button_clicked(self, widget):
year = app.win.calendar.get_property('year')
month = app.win.calendar.get_property('month')
day = app.win.calendar.get_property('day')
start_iter = self.text_view.get_buffer().get_start_iter()
end_iter = self.text_view.get_buffer().get_end_iter()
app.notes_dict[(year, month, day)] = self.text_view.get_buffer().get_text(start_iter, end_iter, True)
app.win.do_update()
self.text_view.get_buffer().set_text("")
self.popdown()
class Window(Gtk.Window):
def __init__(self, app):
Gtk.Window.__init__(self)
self.set_title('Test GtkCalendar')
self.set_default_size(400, 300)
header_bar = Gtk.HeaderBar()
header_bar.set_show_close_button(True)
self.set_titlebar(header_bar)
button = Gtk.Button(label="Add note")
button.get_style_context().add_class('suggested-action')
button.connect('clicked', self.on_button_clicked)
header_bar.pack_start(button)
grid = Gtk.Grid()
grid.set_orientation(Gtk.Orientation.VERTICAL)
self.calendar = Gtk.Calendar()
scrolled_window = Gtk.ScrolledWindow()
self.text_view = Gtk.TextView()
self.add(grid)
grid.add(self.calendar)
grid.add(scrolled_window)
scrolled_window.add(self.text_view)
self.calendar.set_hexpand(True)
self.calendar.set_halign(Gtk.Align.CENTER)
scrolled_window.set_vexpand(True)
scrolled_window.set_hexpand(True)
self.popover = NotePopover(app)
self.popover.set_relative_to(button)
self.connect('destroy', Gtk.main_quit)
self.calendar.connect('day-selected', self.calendar_changed)
self.calendar.connect('month-changed', self.calendar_changed)
self.show_all()
self.app = app
def on_button_clicked(self, widget):
self.popover.do_popup()
def calendar_changed(self, widget):
self.do_update()
def do_update(self):
year = app.win.calendar.get_property('year')
month = app.win.calendar.get_property('month')
day = app.win.calendar.get_property('day')
text = app.notes_dict.get((year, month, day))
if text is not None:
self.text_view.get_buffer().set_text(text)
else:
self.text_view.get_buffer().set_text("")
class Application:
def __init__(self):
self.notes_dict = dict()
self.win = Window(self)
if __name__ == '__main__':
app = Application()
Gtk.main()
I apologize for my bad English.
I need your help. I just bring strategy design pattern, I have understood the pattern with a simple example, but the implementation in my project is very confusing for me, maybe you can help me.
I have for example these two classes:
from tkinter import *
from app.interface.settings import New_Font
from app.controller.interface_elements.button_controller import Button_controller
from app.controller.interface_elements.close_button_controller import Close_button_controller
class New_Button:
def __init__(self, insert_button_in_frame, text, width, position_X, position_Y, background_color, foreground_color, close_button_parameter):
self._number_types = {int, float}
self.set_frame (insert_button_in_frame)
self.set_text (text)
self.set_width (width)
self.set_position (position_X, position_Y)
self.set_color (background_color, foreground_color)
self.set_close_button_parameter (close_button_parameter)
if self.get_text() == 'Abbrechen':
self.controller = Close_button_controller(self.get_close_button_parameter())
else:
self.controller = Button_controller()
self.create_button ()
def create_button(self):
self.set_button(Button(self.get_frame(),
text=self.get_text(),
bg=self.get_background_color(),
fg=self.get_foreground_color(),
width=self.get_width(),
font=New_Font().get_defaultfont(),
command=lambda :self.controller.main_method()))
self.get_button().place(x=self.get_position_X(),
y=self.get_position_Y())
def set_button(self, button):
self._button = button
def get_button(self):
return self._button
def set_frame(self, insert_button_in_frame):
if type(insert_button_in_frame) == Frame:
self._frame = insert_button_in_frame
else: raise TypeError
def get_frame(self):
return self._frame
def set_text(self, text):
if type(text) == str:
self._text = text
else: raise TypeError()
def get_text(self):
return self._text
def set_width(self, width):
if type(width) in self._number_types:
self._width = width
else: raise TypeError
def get_width(self):
return self._width
def set_position(self, position_X , position_Y):
if type(position_X) in self._number_types and type(position_Y) in self._number_types:
self._position_X = position_X
self._position_Y = position_Y
else: raise TypeError
def get_position_X(self):
return self._position_X
def get_position_Y(self):
return self._position_Y
def set_color(self, background_color, foreground_color):
if type(background_color) == str and type(foreground_color) == str:
self._background_color = background_color
self._foreground_color = foreground_color
else: raise TypeError
def get_background_color(self):
return self._background_color
def get_foreground_color(self):
return self._foreground_color
def set_controller(self, controller):
self._controller = controller
def get_controller(self):
return self._controller
def set_info(self, search_for):
self._info = self.get_button().cget(search_for)
def get_info(self):
return self._info
def set_close_button_parameter(self, close_button_parameter):
self._close_button_parameter = close_button_parameter
def get_close_button_parameter(self):
return self._close_button_parameter
and
from app.gui.top_frame import *
from app.interface.settings import New_Font
from app.controller.interface_elements.radiobutton_controller import Radiobutton_controller
class New_Radiobutton:
def __init__(self, frame_to_insert_radiobutton, radiobutton_label, button_horizontal_position, button_vertical_position, radiobutton_group, radiobutton_value, crawled_radiobuttons):
self._number_types = {int, float}
self._allowed_group_types = {int, float, str}
self._values = {1,3,5}
self._disable = {3,4,5,6}
self.set_frame_to_insert_radiobutton (frame_to_insert_radiobutton)
self.set_radiobutton_label (radiobutton_label)
self.set_position (button_horizontal_position, button_vertical_position)
self.set_radiobutton_group (radiobutton_group)
self.set_radiobutton_value (radiobutton_value)
self.create_radiobutton()
self._radiobutton_controller = Radiobutton_controller(crawled_radiobuttons)
self.set_first_radiobutton_of_a_group()
def create_radiobutton(self):
self.set_radiobutton(Radiobutton(self.get_frame_to_insert_radiobutton(),
text=self.get_radiobutton_label(),
variable=self.get_radiobutton_group(),
value=self.get_radiobutton_value(),
font=New_Font().get_defaultfont(),
command= lambda : self._radiobutton_controller.main_method()))
self.get_radiobutton().place(x=self.get_button_horizontal_position(),
y=self.get_button_vertical_position())
def set_first_radiobutton_of_a_group(self):
if self.get_radiobutton_value() in self._values:
self.get_radiobutton().invoke()
if self.get_radiobutton_value() in self._disable:
self.get_radiobutton().config(state=DISABLED)
def get_frame_to_insert_radiobutton(self):
return self._frame_to_insert_radiobutton
def set_frame_to_insert_radiobutton(self, frame_to_insert_radiobutton):
if type(frame_to_insert_radiobutton) == tkinter.Frame:
self._frame_to_insert_radiobutton = frame_to_insert_radiobutton
else: raise TypeError(frame_to_insert_radiobutton +
' frame_to_insert_radiobutton i not from type tkinter.Frame')
def get_radiobutton_label(self):
return self._radiobutton_label
def set_radiobutton_label(self, radiobutton_label):
if type(radiobutton_label) == str:
self._radiobutton_label = radiobutton_label
else: raise TypeError(radiobutton_label +
' radiobutton_label is not from type string')
def get_button_horizontal_position(self):
return self._button_horizontal_position
def get_button_vertical_position(self):
return self._button_vertical_position
def set_position(self, button_horizontal_position, button_vertical_position):
if type(button_horizontal_position) and type(button_vertical_position) in self._number_types:
self._button_horizontal_position = button_horizontal_position
self._button_vertical_position = button_vertical_position
else: raise TypeError(button_horizontal_position + ' ' + button_vertical_position +
' button_horizontal_position or button_vertical_position or both is/are not from type number')
def get_radiobutton_group(self):
return self._radiobutton_group
def set_radiobutton_group(self, radiobutton_group):
if type(radiobutton_group) in self._allowed_group_types:
self._radiobutton_group = radiobutton_group
else: raise TypeError(radiobutton_group +
' radiobutton_group is not from type int/float or string')
def get_radiobutton_value(self):
return self._radiobutton_value
def set_radiobutton_value(self, radiobutton_value):
if type(radiobutton_value) in self._number_types:
self._radiobutton_value = radiobutton_value
else: raise TypeError(radiobutton_value +
'radiobutton_value is not from type number')
def get_radiobutton_controller(self, radiobutton_controller):
return self.get_radiobutton().cget(radiobutton_controller)
def set_radiobutton(self, radiobutton):
self._radiobutton = radiobutton
def get_radiobutton(self):
return self._radiobutton
both classes need 90% the same methods and I have 2 other methods where it is. how do I start encapsulating the changeable now? because the button, no matter if radio, checkbox or button, is only created with the create method
thank you for your help
I am writing a fuzzy search application which finds words in text even if words have mistakes. I wrote gui form but it freezed because of heavy calculation. So I created class inherited from QThread and emitted signals from it to gui so that progress bar started to work and gui form wasn't freezed anymore. BUT I should also create console version of this application where I don't need gui form but I need methods that written in class inherited from QThread. But it's impossible without using PyQT library which strange to use in console version. So I don't know how to solve this problem. My teacher recommended to use threading but I didn't find how to emit signals from Thread class as I colud do in QThread.
That's a QThread class
import text_methods
from PyQt5.QtCore import pyqtSignal, QThread
class FuzzySearch(QThread):
sig_words_count = pyqtSignal(int)
sig_step = pyqtSignal(int)
sig_done = pyqtSignal(bool)
sig_insertions = pyqtSignal(str)
sig_insertions_indexes = pyqtSignal(list)
def __init__(self, text, words, case_sensitive):
super().__init__()
self.text = text
self.words = words
self.case_sensitive = case_sensitive
self.insertions_indexes = {}
self.text_dict = {}
def run(self):
self.get_insertions_info(self.text, self.words)
def find_insertions_of_word(self, word, word_number):
word_insertions = {}
for textword in self.text_dict.keys():
if text_methods.is_optimal_distance(word, textword):
word_insertions[textword] = self.text_dict[textword]
for index in self.text_dict[textword]:
self.insertions_indexes[index] = index + len(textword)
self.sig_step.emit(word_number)
return word_insertions
'''Get information about insertions of words in the text'''
def find_insertions(self, text, words):
word_number = 1
insertions = {}
self.text_dict = text_methods.transform_text_to_dict(text, self.case_sensitive)
words_list = text_methods.transform_words_to_list(words, self.case_sensitive)
self.sig_words_count.emit(len(words_list))
for word in words_list:
print(word_number)
insertions[word] = self.find_insertions_of_word(word, word_number)
word_number += 1
self.insertions_indexes = sorted(self.insertions_indexes.items())
return insertions
'''Get information about insertions of words in the text in special format'''
def get_insertions_info(self, text, words):
insertions = self.find_insertions(text, words)
insertions_info = ''
for word in insertions.keys():
insertions_info += 'Вы искали слово "' + word + '"\n'
if len(insertions[word]) == 0:
insertions_info += ' По этому запросу не было найдено слов\n'
else:
insertions_info += ' По этому запросу были найдены слова:\n'
for textword in insertions[word].keys():
insertions_info += ' "' + textword + '" на позициях: '
insertions_info += ", ".join([str(i) for i in insertions[word][textword]])
insertions_info += '\n'
self.sig_done.emit(True)
self.sig_insertions.emit(insertions_info)
self.sig_insertions_indexes.emit(self.insertions_indexes)
self.quit()
As you see there are a lot of emitted signals that I transfer to gui module where they connect to slots in class FindButton in method find_insertions:
from PyQt5.QtWidgets import QHBoxLayout, QVBoxLayout, QApplication, QWidget,\
QLabel, QPushButton, QTextEdit, QFileDialog,\
QMessageBox, QProgressBar, QCheckBox
from PyQt5.QtCore import Qt
from PyQt5.QtGui import QFont
from fuzzysearch import FuzzySearch
import sys
class OpenButton(QPushButton):
def __init__(self, name, font, textedit):
super().__init__(name, font=font)
self.textedit = textedit
self.clicked.connect(self.open_dialog)
def open_dialog(self):
fname = QFileDialog.getOpenFileName(self, 'Open file', '/home')
if fname[0]:
with open(fname[0], 'r') as f:
data = f.read()
self.textedit.setText(data)
class FindButton(QPushButton):
def __init__(self, name, font, text, words, result, window):
super().__init__(name, font=font)
self.window = window
self.textedit = text
self.wordsedit = words
self.resultedit = result
self.checkbox = window.case_sensitive_checkbox
self.clicked.connect(self.find_insertions)
def find_insertions(self):
text = self.textedit.toPlainText()
words = self.wordsedit.toPlainText()
if text == '':
QMessageBox.information(self, 'Нет текста',
'Текст не был введен. \nВведите текст.')
elif words == '':
QMessageBox.information(self, 'Нет слов',
'Слова не были введены. \nВведите слова через запятую.')
else:
self.setDisabled(True)
self.text_editor = TextEditor(text, self.textedit)
self.fuzzy_search = FuzzySearch(text, words, self.checkbox.checkState())
self.fuzzy_search.sig_words_count.connect(self.window.progress_bar.setMaximum)
self.fuzzy_search.sig_step.connect(self.window.progress_bar.setValue)
self.fuzzy_search.sig_done.connect(self.setEnabled)
self.fuzzy_search.sig_insertions.connect(self.resultedit.setText)
self.fuzzy_search.sig_insertions_indexes.connect(self.text_editor.mark)
self.fuzzy_search.start()
class TextEditor:
def __init__(self, text, textedit):
self.text = text
self.textedit = textedit
def mark(self, to_mark):
self.textedit.clear()
current_index = 0
for item in to_mark:
self.write_not_marked_text(self.text[current_index:item[0]])
self.write_marked_text(self.text[item[0]:item[1]])
current_index = item[1]
self.write_not_marked_text(self.text[current_index:])
def write_not_marked_text(self, text):
font = QFont("Times", 10)
font.setItalic(False)
font.setBold(False)
self.textedit.setCurrentFont(font)
self.textedit.setTextColor(Qt.black)
self.textedit.insertPlainText(text)
def write_marked_text(self, text):
font = QFont("Times", 10)
font.setItalic(True)
font.setBold(True)
self.textedit.setCurrentFont(font)
self.textedit.setTextColor(Qt.red)
self.textedit.insertPlainText(text)
class Window(QWidget):
def __init__(self, font):
super().__init__()
self.standard_font = font
self.text_edit_font = QFont("Times", 10)
text_label = QLabel("Введите или откройте текст",
font=self.standard_font)
words_label = QLabel("Введите или откройте слова (через запятую)",
font=self.standard_font)
result_label = QLabel("Результат",
font=self.standard_font)
text_edit = QTextEdit(font=self.text_edit_font)
words_edit = QTextEdit(font=self.text_edit_font)
result_edit = QTextEdit(font=self.text_edit_font)
self.case_sensitive_checkbox = QCheckBox('Учитывать регистр')
self.case_sensitive_checkbox.setFont(self.standard_font)
self.progress_bar = QProgressBar()
self.progress_bar.setValue(0)
open_btn1 = OpenButton("Открыть", self.standard_font, text_edit)
open_btn2 = OpenButton("Открыть", self.standard_font, words_edit)
find_btn = FindButton("Найти слова в тексте", self.standard_font,
text_edit, words_edit, result_edit, self)
text_label_box = QHBoxLayout()
text_label_box.addWidget(text_label, alignment=Qt.AlignLeft)
text_label_box.addWidget(open_btn1, alignment=Qt.AlignRight)
words_label_box = QHBoxLayout()
words_label_box.addWidget(words_label, alignment=Qt.AlignLeft)
words_label_box.addWidget(open_btn2, alignment=Qt.AlignRight)
words_box = QVBoxLayout()
words_box.addLayout(words_label_box)
words_box.addWidget(words_edit)
result_box = QVBoxLayout()
result_box.addWidget(result_label, alignment=Qt.AlignLeft)
result_box.addWidget(result_edit)
bottom_box = QHBoxLayout()
bottom_box.addLayout(words_box)
bottom_box.addLayout(result_box)
find_and_progress_box = QHBoxLayout()
find_and_progress_box.addWidget(find_btn, alignment=Qt.AlignLeft)
find_and_progress_box.addWidget(self.case_sensitive_checkbox)
find_and_progress_box.addWidget(self.progress_bar)
main_box = QVBoxLayout()
main_box.addLayout(text_label_box)
main_box.addWidget(text_edit)
main_box.addLayout(bottom_box)
main_box.addLayout(find_and_progress_box)
self.setLayout(main_box)
self.setGeometry(300, 300, 1100, 700)
self.setWindowTitle('Нечеткий поиск')
self.show()
def start_application():
app = QApplication(sys.argv)
w = Window(QFont("Times", 12))
sys.exit(app.exec_())
And it works perfectly. But it will not work in console version because without QEventLoop QThread will not work:
import fuzzysearch
class ConsoleVersion():
def __init__(self, text, words):
self.text = text
self.words = words
def search_words_in_text(self):
with self.text:
with self.words:
self.f = fuzzysearch.FuzzySearch(self.text.read(), self.words.read(), False)
self.f.sig_insertions.connect(self.get_insertions)
self.f.start()
def get_insertions(self, insertions):
print(insertions)
and in main file I wrote parsing arguments and choise between two versions
import argparse
import gui
import console_version
def parse_args():
parser = argparse.ArgumentParser(description='Fuzzy search in text')
parser.add_argument('-g', '--graphics', help='graphical version', action='store_true')
parser.add_argument('-c', '--console', help='console version', nargs=2, type=argparse.FileType('r'), metavar=('TEXTFILE', 'WORDSFILE'))
return parser.parse_args()
if __name__ == '__main__':
args = parse_args()
if args.graphics:
gui.start_application()
if args.console:
cv = console_version.ConsoleVersion(args.console[0], args.console[1])
cv.search_words_in_text()
and module text_methods:
from re import split, sub
def transform_text_to_dict(text, case_sensitive):
text_dict = {}
index = 0
if case_sensitive:
splitted_text = split("[^'а-яА-ЯA-Za-z0-9_-]", text)
else:
splitted_text = split("[^'а-яА-ЯA-Za-z0-9_-]", text.lower())
for element in splitted_text:
if element not in text_dict:
text_dict[element] = []
text_dict[element].append(index)
index += len(element) + 1
return text_dict
def transform_words_to_list(words, case_sensitive):
words = sub("^\s+|\n|\r|\s+$", '', words)
if case_sensitive:
return split(' *, *', words)
else:
return split(' *, *', words.lower())
'''Damerau-Levenstein'''
def find_distance(word1: str, word2: str):
len1, len2 = len(word1), len(word2)
if len1 > len2:
word1, word2 = word2, word1
len1, len2 = len2, len1
current_row = range(len1 + 1)
previous_row = range(len1 + 1)
pre_previous_row = range(len1 + 1)
for i in range(1, len2 + 1):
if i == 1:
previous_row, current_row = current_row, [i] + [0] * len1
else:
pre_previous_row, previous_row, current_row = previous_row, current_row, [i] + [0] * len1
for j in range(1, len1 + 1):
add = previous_row[j] + 1
delete = current_row[j - 1] + 1
change = previous_row[j - 1]
if word1[j - 1] != word2[i - 1]:
change += 1
if word1[j - 1] == word2[i - 2] and word1[j - 2] == word2[i - 1]:
transpose = pre_previous_row[j - 2] + 1
current_row[j] = min(add, delete, change, transpose)
else:
current_row[j] = min(add, delete, change)
return current_row[len1]
def is_optimal_distance(word1 : str, word2 : str):
distance = find_distance(word1, word2)
l = min(len(word1), len(word2))
return distance <= l // 4
so what can you advise me?
Qt so that to handle the tasks always needs a loop that is created internally for it one must construct an object of the type QCoreApplication, QGuiApplication or QApplication, this needs it for example for this case for QThread that is not a thread but a thread handler for that is monitoring the state of the thread, if you do not place the application is closed immediately since the run method is not executed in the main thread.
if args.console:
app = QCoreApplication(sys.argv)
cv = console_version.ConsoleVersion(args.console[0], args.console[1])
cv.search_words_in_text()
sys.exit(app.exec_())
I'm trying to build a logging application that stores date, exercise type, duration and comments in a database. It renders the form as i expect it but it does not create the database table from my base class. I just got stuck and hope anyone can help me what's going wrong.
CHOICES = [
(None, 'Choose Exercise'),
('Aerobics', 'Aerobics'),
('Box & Kick', 'Box & Kick'),
('Circle Training', 'Circle Training'),
('Core', 'Core'),
('Afrodance', 'Afro Dance'),
('HIT', 'HIT'),
('StepUp', 'StepUp'),
('Zumba', 'Zumba')]
class AerobicExercise(models.Model):
date = models.DateField(default='YYYYMMDD')
duration = models.DurationField()
comment = models.TextField(blank=True)
exercise = models.CharField(choices=CHOICES, max_length=20)
def __str__(self):
return self.exercise
class SplitDurationWidget(forms.MultiWidget):
def __init__(self, attrs=None):
widgets = (forms.NumberInput(attrs=attrs),
forms.NumberInput(attrs=attrs),
forms.NumberInput(attrs=attrs))
super(SplitDurationWidget, self).__init__(widgets, attrs)
def decompress(self, value):
if value:
hours = value.seconds // 3600
minutes = (value.seconds % 3600) // 60
seconds = value.seconds % 60
return [int(value.days), int(hours), int(minutes), int(seconds)]
return [0, 0, 0, 0]
class Duration(MultiValueField):
widget = SplitDurationWidget
def __init__(self, *args, **kwargs):
fields = (
forms.IntegerField(),
forms.IntegerField(),
forms.IntegerField(),
)
super(Duration, self).__init__(
fields=fields,
require_all_fields=True, *args, **kwargs
)
def compress(self, data_list):
if len(data_list) == 3:
return timedelta(
hours=int(data_list[0]),
minutes=int(data_list[1]),
seconds=int(data_list[2])
)
else:
return timedelta(0)
class AerobicForm(ModelForm):
def __init__(self, *args, **kwargs):
super(AerobicForm, self).__init__(*args, **kwargs)
self.fields['duration'] = Duration()
date = forms.DateField(initial=datetime.date.today())
class Meta:
model = AerobicExercise
fields = '__all__'
localized_fields = ('date',)
widgets = {
'comment': Textarea(attrs={'placeholder': 'The highlight of this workout was...'}),
}