Dropdown menus inluding dates ( From Date1 To Date2 ) in PysimpleGUI - list

Dears,
I am looking for a PysimpleGUI way to create dropdown menus which includes range of dates ( only years) , instead of writting the whole list in sg.combo () function or instaed of Choosing Sg.CalendarButton, which are both not useful in my case :
I want something like the below :
import PySimpleGui as sg
sg.Combo([range(Date1 To Date2)], size=(6, 1), font=("Helvetica", 10), key='Dates'),)
Thanks in advance

[range(Date1 To Date2)] is a list with only one item which is is a class of immutable iterable objects.
Example Code
import datetime
import PySimpleGUI as sg
def date(year, month=1, day=1):
return datetime.date(year, month=month, day=day)
def get_years(start, stop):
return list(range(start.year, stop.year+1))
start = date(2022)
stop = date(2030)
dates = get_years(start, stop)
layout = [[sg.Combo(dates, font=("Helvetica", 10), size=(5, 5), enable_events=True, key='Dates')]]
window = sg.Window('Title', layout)
while True:
event, values = window.read()
if event == sg.WIN_CLOSED:
break
item = values['Dates']
print(item, ":", type(item))
window.close()
2024 : <class 'int'>

Related

Binding a function to a combobox in python tkinter

I am a newbie to python and tkinter and I ran into a problem as I was practicing on Combobox. I wrote this code with two dependent combobox. If in the first combobox, 'Jan' is selected, the second one will be enabled and automatically give 'J' as the only choice to choose from.
When I ran my code and selected 'Jan' in Combobox1, the combobox 2 was enabled, but it didn't have any value (in this case 'J').
Can someone help me with this?
import ttk
root = Tk()
root.geometry("400x400")
month = StringVar()
combobox1 = ttk.Combobox(root, textvariable = month)
combobox1.config(values = ('Jan', 'Feb', 'August'))
combobox1.pack()
date = StringVar()
global comb2
comb2 = ttk.Combobox(root, textvariable = date)
comb2.pack()
comb2.config(state=DISABLED)
def comb1_selected(*args):
if (combobox1.current() != -1 ):
comb2.config(state='normal')
if combobox1.current() == "Jan":
comb2.config(values=('J'))
combobox1.bind("<<ComboboxSelected>>", comb1_selected)
root.mainloop()```
Combobox.current() returns the index of the selected item. In your case it is 0.
If you want to get the value of the selected item, you should use Combobox.get().
def comb1_selected(*args):
if (combobox1.current() != -1 ):
print('current: ' + str(combobox1.current())) #current: 0
print('get: ' + combobox1.get()) #get: Jan
comb2.config(state='normal')
if combobox1.get() == 'Jan':
comb2.config(values=('J'))

How should I link specific rows to columns in a Qtablewidget

I have a Qtablewidget with 3 columns. The first column contain user names, the second and third are columns are check boxes. I would like these check boxes to be attributes for the row of users. For example If you look at the image below, User: bruno is marked(has attributes) delete and delete home. I would like to have an output like: User Bruno marked for delete, marked for delete home. To do that, I would need to link the users to both these columns which I haven't the slightest idea. How should I approach this problem. Below is the code that I already came up with. It populates the users column from a file.
from PyQt4 import QtGui, QtCore
class Window(QtGui.QWidget):
def __init__(self, rows, columns):
QtGui.QWidget.__init__(self)
self.table = QtGui.QTableWidget(rows, columns, self)
self.table.setHorizontalHeaderItem(0, QtGui.QTableWidgetItem("Users"))
self.table.setHorizontalHeaderItem(1, QtGui.QTableWidgetItem("Delete User"))
self.table.setHorizontalHeaderItem(2, QtGui.QTableWidgetItem("Delete User and Home"))
self.table.verticalHeader().hide()
header = self.table.horizontalHeader()
header.setStretchLastSection(True)
rowf = 0
with open("/home/test1/data/users") as in_file:
if in_file is not None:
users = in_file.readlines()
for line in users:
users = QtGui.QTableWidgetItem()
self.table.setItem(rowf, 0, users)
users.setText(line)
rowf+=1
in_file.close()
for column in range(columns):
for row in range(rows):
if column % 3:
item = QtGui.QTableWidgetItem(column)
item.setFlags(QtCore.Qt.ItemIsUserCheckable |
QtCore.Qt.ItemIsEnabled)
item.setCheckState(QtCore.Qt.Unchecked)
self.table.setItem(row, column, item)
self.table.itemClicked.connect(self.cell_was_clicked)
layout = QtGui.QVBoxLayout(self)
layout.addWidget(self.table)
self._list = []
def cell_was_clicked(self, item):
#row = self.table.currentItem().row()
#col = self.table.currentItem().column()
#print "item:", item
#print "row=", row
if item.checkState() == QtCore.Qt.Checked:
print('"%s" Checked' % item.text())
#self._list.append(item.row())
else:
#print "(", row , ",", col, ")"
print('%s' % item.text())
print (item.row(),item.column())
if __name__ == '__main__':
import sys
app = QtGui.QApplication(sys.argv)
window = Window(200, 3)
window.resize(400, 400)
window.show()
sys.exit(app.exec_())
fixed it like this:
def cell_was_clicked(self, item):
if item.checkState() == QtCore.Qt.Checked:
user = self.table
delete = user.horizontalHeaderItem(item.column()).text()
print ('%s' % user.item(item.row(), 0).text())
print ('is marked for %s' % delete)
print('%s Checked' % item.text())
#self._list.append(item.row())
else:
print('%s' % item.text())
print (item.row(),item.column())

ValueError: Shape of passed values is (6, 251), indices imply (6, 1)

I am getting an error and I'm not sure how to fix it.
Here is my code:
from matplotlib.finance import quotes_historical_yahoo_ochl
from datetime import date
from datetime import datetime
import pandas as pd
today = date.today()
start = (today.year-1, today.month, today.day)
quotes = quotes_historical_yahoo_ochl('AXP', start, today)
fields = ['date', 'open', 'close', 'high', 'low', 'volume']
list1 = []
for i in range(len(quotes)):
x = date.fromordinal(int(quotes[i][0]))
y = datetime.strftime(x, '%Y-%m-%d')
list1.append(y)
quotesdf = pd.DataFrame(quotes, index = list1, columns = fields)
quotesdf = quotesdf.drop(['date'], axis = 1)
print quotesdf
How can I change my code to achieve my goal, change the dateform and delete the original one?
In principle your code should work, you just need to indent it correctly, that is, you need to append the value of y to list1 inside the for loop.
for i in range(len(quotes)):
x = date.fromordinal(int(quotes[i][0]))
y = datetime.strftime(x, '%Y-%m-%d')
list1.append(y)
Thereby list1 will have as many entries as quotes instead of only one (the last one). And the final dataframe will not complain about misshaped data.

How to turn Python integer into datetime

I have a simple PyQt GUI which gives values which I would like to turn into a datetime format.
At the moment it is printing
201011
Whereas I would like it to print
2010,1,1
Here is the PyQt code,
*timer.py
from PyQt4 import QtCore, QtGui
try:
_fromUtf8 = QtCore.QString.fromUtf8
except AttributeError:
def _fromUtf8(s):
return s
try:
_encoding = QtGui.QApplication.UnicodeUTF8
def _translate(context, text, disambig):
return QtGui.QApplication.translate(context, text, disambig, _encoding)
except AttributeError:
def _translate(context, text, disambig):
return QtGui.QApplication.translate(context, text, disambig)
class Ui_Dialog(object):
def setupUi(self, Dialog):
Dialog.setObjectName(_fromUtf8("Dialog"))
Dialog.resize(510, 129)
self.gridLayout = QtGui.QGridLayout(Dialog)
self.gridLayout.setObjectName(_fromUtf8("gridLayout"))
self.frame = QtGui.QFrame(Dialog)
self.frame.setFrameShape(QtGui.QFrame.StyledPanel)
self.frame.setFrameShadow(QtGui.QFrame.Raised)
self.frame.setObjectName(_fromUtf8("frame"))
self.gridLayout_2 = QtGui.QGridLayout(self.frame)
self.gridLayout_2.setObjectName(_fromUtf8("gridLayout_2"))
self.yearlabel = QtGui.QLabel(self.frame)
self.yearlabel.setObjectName(_fromUtf8("yearlabel"))
self.gridLayout_2.addWidget(self.yearlabel, 0, 0, 1, 1)
self.monthfromcomboBox = QtGui.QComboBox(self.frame)
self.monthfromcomboBox.setObjectName(_fromUtf8("monthfromcomboBox"))
self.gridLayout_2.addWidget(self.monthfromcomboBox, 1, 2, 1, 2)
self.label_2 = QtGui.QLabel(self.frame)
self.label_2.setObjectName(_fromUtf8("label_2"))
self.gridLayout_2.addWidget(self.label_2, 0, 4, 1, 1)
self.SearchButton = QtGui.QPushButton(self.frame)
self.SearchButton.setObjectName(_fromUtf8("SearchButton"))
self.gridLayout_2.addWidget(self.SearchButton, 2, 4, 1, 2)
self.yearfromcomboBox = QtGui.QComboBox(self.frame)
self.yearfromcomboBox.setObjectName(_fromUtf8("yearfromcomboBox"))
self.gridLayout_2.addWidget(self.yearfromcomboBox, 1, 0, 1, 2)
self.dayfromcomboBox = QtGui.QComboBox(self.frame)
self.dayfromcomboBox.setObjectName(_fromUtf8("dayfromcomboBox"))
self.gridLayout_2.addWidget(self.dayfromcomboBox, 1, 4, 1, 2)
self.label = QtGui.QLabel(self.frame)
self.label.setObjectName(_fromUtf8("label"))
self.gridLayout_2.addWidget(self.label, 0, 2, 1, 1)
self.gridLayout.addWidget(self.frame, 0, 0, 1, 1)
self.retranslateUi(Dialog)
QtCore.QMetaObject.connectSlotsByName(Dialog)
Dialog.setTabOrder(self.yearfromcomboBox, self.monthfromcomboBox)
Dialog.setTabOrder(self.monthfromcomboBox, self.dayfromcomboBox)
def retranslateUi(self, Dialog):
Dialog.setWindowTitle(_translate("Dialog", "Dialog", None))
self.yearlabel.setText(_translate("Dialog", "Year", None))
self.label_2.setText(_translate("Dialog", "Day", None))
self.SearchButton.setText(_translate("Dialog", "Go", None))
self.label.setText(_translate("Dialog", "Month", None))
The corresponding python code is,
import sys
import datetime
from PyQt4 import QtCore, QtGui
from timer import *
from PyQt4.QtGui import (QApplication, QTabWidget, QWidget,
QStyle, QStyleFactory)
class Window(QtGui.QDialog):
def __init__(self, parent=None):
QtGui.QWidget.__init__(self, parent)
self.ui = Ui_Dialog()
self.ui.setupUi(self)
style = QStyleFactory.create('Cleanlooks')
app.setStyle(style)
QtCore.QObject.connect(self.ui.SearchButton, QtCore.SIGNAL('clicked()'), self.search)
months = range(1,13)
for iitem in months:
Months = str(iitem)
self.ui.monthfromcomboBox.addItem(Months)
days = range(1,32)
for iitem in days:
Days = str(iitem)
self.ui.dayfromcomboBox.addItem(Days)
years = range(2010, 2017)
for iitem in years:
Years = str(iitem)
self.ui.yearfromcomboBox.addItem(Years)
def search(self):
nowyear = int(self.ui.yearfromcomboBox.currentText())
nowmonth = int(self.ui.monthfromcomboBox.currentText())
nowday = int(self.ui.dayfromcomboBox.currentText())
nowdate = int('%d%d%d' %(nowyear,nowmonth,nowday))
print nowdate
if __name__ == "__main__":
app = QtGui.QApplication(sys.argv)
viewer = Window()
viewer.show()
sys.exit(app.exec_())
I'd recommend using datetime.datetime.strptime:
from datetime import datetime
date_int = 201011
date = datetime.strptime(str(date_int), '%Y%m%d')
print '{},{},{}'.format(date.year, date.month, date.day)
2010,1,1
Here is my solution:
dateNum = 201011
dateNum = str(dateNum)
year = dateNum[:4]
monthDay = dateNum[4:]
if len(monthDay) == 2:
day = monthDay[1:]
month = monthDay[:1]
print(year + "," + month + "," + day)
This will output:
2010,1,1
The only problem with this code is that you cannot determine dates such as:
2014111 which should be November 1st but could also be January 11th
Is there any way you can change the format to include leading zeros? (e.g. 20141101 for Nov 1st 2014)
Maybe someone else has a way to determine this. However I think logically the format makes it impossible to determine one or the other.
This code is redefined to handle the leading zeros:
dateNum = 20100101
dateNum = str(dateNum)
year = dateNum[:4]
monthDay = dateNum[4:]
day = monthDay[2:]
month = monthDay[:2]
print(year + "," + month + "," + day)
2010,01,01
There's no reason to convert your date parts into a string and then to an single integer if you don't actually need that integer for something. Get rid of this line:
nowdate = int('%d%d%d' %(nowyear,nowmonth,nowday))
And instead use the individiual date components however you want. It could be as simple as print nowyear, nowmonth, nowday (which will print them separated by spaces), or you could do something more complicated like using them to create something from the datetime module which you can use later (or print in a wide variety of formats).
To get the output you specifically request ('2010,1,1'), you can keep it pretty close to your existing code. Just use print '%d,%d,%d' % (nowyear, nowmonth, nowday), or if you want to use the newer str.format syntax, print '{:d},{:d},{:d}'.format(nowyear, nowmonth, nowday). If you wanted the single-digit month or days to use two characters (so they're always the same width), you could use %02d or {:02d} in the format strings, to request zero-padding to a width of two.

Django: Total birthdays each day for the next 30 days

I've got a model similar to this:
class Person(models.Model):
name = models.CharField(max_length=40)
birthday = DateTimeField() # their next birthday
I would like to get a list of the total birthdays for each day for the next 30 days. So for example, the list would look like this:
[[9, 0], [10, 3], [11, 1], [12, 1], [13, 5], ... #30 entries in list
Each list entry in the list is a date number followed by the number of birthdays on that day. So for example on the 9th of May there are 0 birthdays.
UPDATES
My db is sqlite3 - will be moving to postgres in the future.
from django.db.models import Count
import datetime
today = datetime.date.today()
thirty_days = today + datetime.timedelta(days=30)
birthdays = dict(Person.objects.filter(
birthday__range=[today, thirty_days]
).values_list('birthday').annotate(Count('birthday')))
for day in range(30):
date = today + datetime.timedelta(day)
print "[%s, %s]" % (date, birthdays.get(date, 0))
I would get the list of days and birthday count this way:
from datetime import date, timedelta
today = date.today()
thirty_days = today + timedelta(days=30)
# get everyone with a birthday
people = Person.objects.filter(birthday__range=[today, thirty_days])
birthday_counts = []
for date in [today + timedelta(x) for x in range(30)]:
# use filter to get only birthdays on given date's day, use len to get total
birthdays = [date.day, len(filter(lambda x: x.birthday.day == date.day, people))]
birthday_counts.append(birthdays)
Something like this --
from datetime import date, timedelta
class Person(models.Model):
name = models.CharField(max_length=40)
birthday = models.DateField()
#staticmethod
def upcoming_birthdays(days=30):
today = date.today()
where = 'DATE_ADD(birthday, INTERVAL (YEAR(NOW()) - YEAR(birthday)) YEAR) BETWEEN DATE(NOW()) AND DATE_ADD(NOW(), INTERVAL %S DAY)'
birthdays = Person.objects.extra(where=where, params=[days]).values_list('birthday', flat=True)
data = []
for offset in range(0, days):
i = 0
d = today + timedelta(days=offset)
for b in birthdays:
if b.day == d.day and b.month == d.month:
i += 1
data.append((d.day, i))
return data
print Person.upcoming_birthdays()
(Queryset of people with a birthday in the next X days)
Found cool solution for this!
For me it works!
from datetime import datetime, timedelta
import operator
from django.db.models import Q
def birthdays_within(days):
now = datetime.now()
then = now + timedelta(days)
# Build the list of month/day tuples.
monthdays = [(now.month, now.day)]
while now <= then:
monthdays.append((now.month, now.day))
now += timedelta(days=1)
# Tranform each into queryset keyword args.
monthdays = (dict(zip(("birthday__month", "birthday__day"), t))
for t in monthdays)
# Compose the djano.db.models.Q objects together for a single query.
query = reduce(operator.or_, (Q(**d) for d in monthdays))
# Run the query.
return Person.objects.filter(query)
But it get a list of persons that have a birthday in date range. You should change a bit.