Build a Remarkably Awesome Interactive Calendar With Python

Nice, but not functional.

Time to Revisit QCalendarWidget

import sys, os
import pandas as pd
from datetime import datetime
from pymongo import MongoClient
from PyQt5.QtCore import QDate, Qt, QRect
from PyQt5.QtGui import (
QFont,
QColor,
QBrush,
QPainter,
QTextCharFormat,

)
from PyQt5.QtWidgets import (
QLabel,
QWidget,
QTextEdit,
QApplication,
QTableWidget,
QCalendarWidget,
QTableWidgetItem,
)
client = MongoClient("localhost", 27017)
db = client["mydb"]
coll = db["appointments"]
class Calendar(QCalendarWidget):    def __init__(self, parent=None):
super(Calendar, self).__init__(parent)
class Appointments():

def appointments(self):
appts = []
now = datetime.now()
today = now.strftime('%m-%d-%Y')

data = coll.find({}, {'_id': 0, 'date': 1, 'time': 1, 'place': 1, 'note': 1}).sort('date')
for _d in data:
if _d['date'] < today:
pass
else:
date, time, place, note = _d['date'][:5], _d['time'], _d['place'], _d['note']
appts.append([date, time, place, note])
return appts
class Example(QWidget):    def __init__(self):
super(Example, self).__init__()
self.initUI()


def initUI(self):
self.left = 1138
self.top = 30
self.width = 302
self.height = 370
self.appointments = Appointments()
self.cal = QCalendarWidget( self )
format = QTextCharFormat()
self.setWindowFlags(Qt.FramelessWindowHint)
self.setGeometry(self.left,self.top,self.width,self.height)
self.setAutoFillBackground(True)
p = self.palette()
p.setColor(self.backgroundRole(), Qt.black)
self.setPalette(p)
qdim = "QPushButton {color: rgba(54, 136, 200, 250); background-color: black; }"
canda_10 = QFont("Candalara", 10)
canda_11 = QFont( "Candalara", 11 )
segoe_9 = QFont('Segoe UI', 9)
format   = self.cal.weekdayTextFormat( Qt.Saturday)
format.setForeground( QBrush( Qt.darkCyan, Qt.SolidPattern ) )
self.cal.setWeekdayTextFormat( Qt.Saturday, format )
self.cal.setWeekdayTextFormat( Qt.Sunday, format )
self.cal.setVerticalHeaderFormat( self.cal.NoVerticalHeader )
self.cal.setGridVisible(False)
self.cal.setGeometry(0, 0, 292, 221)
self.cal.setFont(segoe_9)
self.cal.setStyleSheet(
"QCalendarWidget QAbstractItemView{background-color: black; color: rgba(162,201,229,255); selection-background-color: rgb(20,20,20); selection-color: rgb(200,150,255); selection-border: 1px solid black;}"
"QCalendarWidget QWidget{alternate-background-color: rgb(20, 20, 20); color: gray;}" "QCalendarWidget QToolButton{background-color: black; color: rgb(125,125,125); font-size: 14px; font: bold; width: 70px; border: none;}" "QCalendarWidget QToolButton#qt_calendar_prevmonth{qproperty-icon: url(left_arrow.png);}" "QCalendarWidget QToolButton#qt_calendar_nextmonth{qproperty-icon: url(right_arrow.png);}"
)
self.button = QPushButton(self)
self.button.setStyleSheet(qdim)
self.button.setFont(canda_11)
self.button.setText("EXIT")
self.button.setGeometry(10, 240, 281, 90)
self.button.clicked.connect(self.exit)
self.cal.clicked[QDate].connect(self.showDate)
self.appt_table = QTableWidget( self )
self.appt_table.setGeometry( QRect( 10, 240, 281, 90 ) )
self.appt_table.setStyleSheet(
"QTableWidget {color: rgb(135,135,135); background-color: black; border: none;}"
)
self.appt_table.horizontalHeader().hide()
self.appt_table.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
self.appt_table.setFont( canda_10 )
self.appt_table.verticalHeader().setVisible( False )
data = self.appointments.appointments()
df = pd.DataFrame(data)
self.display_data(df)
self.show()
def display_data(self, var):
self.appt_table.setColumnCount( len( var.columns ) )
self.appt_table.setRowCount( len( var.index ) )

for i in range( len( var.index ) ):
for j in range( len( var.columns ) ):
self.appt_table.setItem( i, j, QTableWidgetItem( str( var.iat[i, j] ) ) )
self.appt_table.resizeColumnsToContents()
def showDate(self, date):
now = QDate.currentDate()
select_date = self.cal.selectedDate()
if select_date < now:
pass
else:
string_date = str(select_date.toPyDate())
self.event_form(string_date)
def event_form(self, string_date):
with open('string_date.txt', 'w') as file:
file.write(string_date)
os.system( r"start /min python event_form.pyw" )
def paintEvent(self, e):
self.painter = QPainter( self )
self.painter.begin( self )
self.painter.setPen(QColor(75, 75, 75))
self.painter.drawLine(50, 230, 250, 230)
self.painter.drawLine(50, 340, 250, 340)
self.painter.end()
def exit(self):
self.close()
if __name__ == "__main__":
app = QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())

The Event Form

import sys
from pymongo import MongoClient
from PyQt5.QtCore import QDate, Qt
from PyQt5.QtGui import (
QPen,
QFont,
QColor,
QBrush,
QPainter,
)
from PyQt5.QtWidgets import (
QLabel,
QWidget,
QLineEdit,
QTextEdit,
QCheckBox,
QComboBox,
QApplication,
)
client = MongoClient("localhost", 27017)
db = client["mydb"]
coll = db["appointments"]
class EventForm(QWidget):
def __init__(self):
super(EventForm, self).__init__()
self.initUI()

def initUI(self):
self.left = 1139
self.top = 253
self.width = 301
self.height = 370
self.setWindowFlags(Qt.FramelessWindowHint)
self.setGeometry(self.left,self.top,self.width,self.height)
self.setAutoFillBackground(True)
p = self.palette()
p.setColor(self.backgroundRole(), Qt.black)
self.setPalette(p)
qdim = "QPushButton {color: rgba(54, 136, 200, 250); background-color: black; }" segoe_9 = QFont( 'Segoe UI', 9 )
segoe_16 = QFont( "Segoe UI", 16 )
canda_10 = QFont( "Candalara", 10 )
canda_11 = QFont( "Candalara", 11 )
canda_12 = QFont( "Candalara", 12 )
times = [
'All Day','5:00 AM', '5:30 AM', '6:00 AM', '6:30 AM',
'7:00 AM', '7:30 AM', '8:00 AM', '8:30 AM', '9:00 AM',
'9:30 AM', '10:00 AM', '10:30 AM', '11:00 AM', '11:30 AM',
'Noon', '12:30 PM', '1:00 PM', '1:30 PM','2:00 PM',
'2:30 PM', '3:00 PM', '3:30 PM', '4:00 PM', '4:30 PM',
'5:00 PM', '5:30 PM', '6:00 PM',
]
with open('string_date.txt', "r") as file:
data = file.read()
num = datetime.strptime(data, '%Y-%m-%d')
day = str(num.strftime( '%A' ))
date = str(num.strftime('%m-%d-%Y'))
self.date_data = QLabel(self)
self.date_data.setGeometry( 0, 15, 301, 40 )
self.date_data.setStyleSheet( "QLabel {color: rgba(125,125,125,255); background-color: black;}" )
self.date_data.setFont( segoe_16 )
self.date_data.setAlignment(Qt.AlignCenter)
self.date_data.setText(day + " " + date)
self.time_label = QLabel(self)
self.time_label.setGeometry(15, 70, 80, 40)
self.time_label.setStyleSheet( "QLabel {color: rgba(125,125,125,255); background-color: black;}" )
self.time_label.setFont(canda_11)
self.time_label.setText("Time")
self.place_label = QLabel(self)
self.place_label.setGeometry(15, 115, 80, 40)
self.place_label.setStyleSheet( "QLabel {color: rgba(125,125,125,255); background-color: black;}" )
self.place_label.setFont(canda_11)
self.place_label.setText("Place")

self.note_label = QLabel(self)
self.note_label.setGeometry( 15, 160, 80, 40 )
self.note_label.setStyleSheet( "QLabel {color: rgba(125,125,125,255); background-color: black;}" )
self.note_label.setFont( canda_11 )
self.note_label.setText( "Note" )
self.time_cbox = QComboBox( self )
self.time_cbox.setGeometry( 70, 75, 100, 30 )
self.time_cbox.setStyleSheet( "QComboBox {color: rgba(125,125,125,255); background-color: black;}" )
self.time_cbox.setFont( canda_11 )
for time in times:
self.time_cbox.addItem(time)
self.time_cbox.currentIndexChanged.connect(self.selectionchange)
self.place_edit = QLineEdit( self )
self.place_edit.setGeometry(70, 120, 215, 30 )
self.place_edit.setStyleSheet( "QLineEdit {color: rgba(125,125,125,255); background-color: rgba(29, 29, 29, 150); border: none;}" )
self.place_edit.setFont( canda_12 )

self.note_edit = QTextEdit(self)
self.note_edit.setGeometry( 70, 165, 215, 80 )
self.note_edit.setStyleSheet( "QTextEdit {color: rgba(125,125,125); background-color: rgba(29, 29, 29, 150); border: none;}" )
self.note_edit.setFont( canda_12 )
self.save = QPushButton(self)
self.save.setStyleSheet(qdim)
self.save.setFont(canda_10)
self.save.setText("SAVE")
self.save.setGeometry(120, 295, 60, 50)
self.save.clicked.connect(self.save)
self.exit = QPushButton(self)
self.exit.setStyleSheet(qdim)
self.exit.setFont(canda_10)
self.exit.setText("EXIT")
self.exit.setGeometry(210, 295, 60, 50)
self.exit.clicked.connect(self.exit)
self.sav-exit = QPushButton(self)
self.sav-exit.setStyleSheet(qdim)
self.sav-exit.setFont(canda_10)
self.sav-exit.setText("SAVE\nEXIT")
self.sav-exit.setGeometry(10, 240, 281, 90)
self.sav-exit.clicked.connect(self.save_exit)
---------------------------------------------Hint: Write a generic button function to shorten your code. For example:def qtbutton(self, name, x, y, w, h, style, font, title, connection):
self.name = QPushButton(self)
self.name.setStyleSheet(style)
self.name.setFont(font)
self.name.setText(title)
self.name.setGeometry(x, y, w, h)
self.name.clicked.connect(connection)
Then you can rewrite the save button function like this:qtbutton(self, 'save', 120, 295, 60, 50, qdim, canda_10, "SAVE", self.save)
def selectionchange(self):
self.place_edit.setFocus()
def paintEvent(self, e):
self.painter = QPainter( self )
self.painter.begin( self )
self.painter.setPen(QColor(75, 75, 75))
self.painter.drawLine(15, 65, 285, 65)
self.painter.drawLine(15, 270, 285, 270 )
self.painter.end()
--------------------------------------------------
Hint: The paintEvent() function is used twice in this project. Write a function to shorten the above code to one line. For example:
def qtpainter(self, color, x, y, w, h):
self.painter = QPainter( self )
self.painter.begin( self )
self.painter.setPen(QColor( color )
self.painter.drawLine(15, 65, 285, 65)
self.painter.end()
To draw a line:qtpainter(self, QColor(75, 75, 75), 15, 65, 285, 65)
def repeat(self):
date = self.date_data.text()[-10:]
time = self.time_cbox.currentText()
place = self.place_edit.text()
note = self.note_edit.toPlainText()
coll.insert_one({'date': date, "time": time, 'place': place, 'note': note})
def save(self):
data = self.repeat()
self.place_edit.clear()
self.note_edit.clear()

def save_exit(self):
data = self.repeat()
self.exit()

def exit(self):
self.close()
if __name__ == "__main__":
app = QApplication(sys.argv)
ex = EventForm()
ex.show()
sys.exit(app.exec_())
# calendar.pywimport sys, os
import pandas as pd
from datetime import datetime
from pymongo import MongoClient
from PyQt5.QtCore import QDate, Qt, QRect
from PyQt5.QtGui import (
QFont,
QColor,
QBrush,
QPainter,
QTextCharFormat,

)
from PyQt5.QtWidgets import (
QLabel,
QWidget,
QTextEdit,
QApplication,
QTableWidget,
QCalendarWidget,
QTableWidgetItem,
)
client = MongoClient("localhost", 27017)
db = client["mydb"]
coll = db["appointments"]
class Calendar(QCalendarWidget): def __init__(self, parent=None):
super(Calendar, self).__init__(parent)
class Appointments():

def appointments(self):
appts = []
now = datetime.now()
today = now.strftime('%m-%d-%Y')

data = coll.find({}, {'_id': 0, 'date': 1, 'time': 1, 'place': 1, 'note': 1}).sort('date')
for _d in data:
if _d['date'] < today:
pass
else:
date, time, place, note = _d['date'][:5], _d['time'], _d['place'], _d['note']
appts.append([date, time, place, note])
return appts
class Example(QWidget): def __init__(self):
super(Example, self).__init__()
self.initUI()


def initUI(self):
self.left = 1138
self.top = 30
self.width = 302
self.height = 370
self.appointments = Appointments()
self.cal = QCalendarWidget( self )
format = QTextCharFormat()
self.setWindowFlags(Qt.FramelessWindowHint)
self.setGeometry(self.left,self.top,self.width,self.height)
self.setAutoFillBackground(True)
p = self.palette()
p.setColor(self.backgroundRole(), Qt.black)
self.setPalette(p)
qdim = "QPushButton {color: rgba(54, 136, 200, 250); background-color: black; }"
canda_10 = QFont("Candalara", 10)
canda_11 = QFont( "Candalara", 11 )
segoe_9 = QFont('Segoe UI', 9)
format = self.cal.weekdayTextFormat( Qt.Saturday)
format.setForeground(QBrush( Qt.darkCyan, Qt.SolidPattern))
self.cal.setWeekdayTextFormat( Qt.Saturday, format )
self.cal.setWeekdayTextFormat( Qt.Sunday, format )
self.cal.setVerticalHeaderFormat(self.cal.NoVerticalHeader)
self.cal.setGridVisible(False)
self.cal.setGeometry(0, 0, 292, 221)
self.cal.setFont(segoe_9)
self.cal.setStyleSheet(
"QCalendarWidget QAbstractItemView{background-color:
black; color: rgba(162,201,229,255); selection-background-color: rgb(20,20,20); selection-color: rgb(200,150,255); selection-border: 1px solid black;}"
"QCalendarWidget QWidget{alternate-background-color:
rgb(20, 20, 20); color: gray;}"
"QCalendarWidget QToolButton{background-color: black;
color: rgb(125,125,125); font-size: 14px; font: bold; width: 70px; border: none;}"
"QCalendarWidget QToolButton#qt_calendar_
prevmonth{qproperty-icon: url(left_arrow.png);}"
"QCalendarWidget QToolButton#qt_calendar_
nextmonth{qproperty-icon: url(right_arrow.png);}"
)
self.button = QPushButton(self)
self.button.setStyleSheet(qdim)
self.button.setFont(canda_11)
self.button.setText("EXIT")
self.button.setGeometry(10, 240, 281, 90)
self.button.clicked.connect(self.exit)
self.cal.clicked[QDate].connect(self.showDate) self.appt_table = QTableWidget( self )
self.appt_table.setGeometry( QRect( 10, 240, 281, 90 ) )
self.appt_table.setStyleSheet(
"QTableWidget {color: rgb(135,135,135); background-color: black; border: none;}"
)
self.appt_table.horizontalHeader().hide()
self.appt_table.setVerticalScrollBarPolicy(
Q
t.ScrollBarAlwaysOff)
self.appt_table.setFont( canda_10 )
self.appt_table.verticalHeader().setVisible( False )
data = self.appointments.appointments()
df = pd.DataFrame(data)
self.display_data(df)
self.show()
def display_data(self, var):
self.appt_table.setColumnCount( len( var.columns ) )
self.appt_table.setRowCount( len( var.index ) )

for i in range( len( var.index ) ):
for j in range( len( var.columns ) ):
self.appt_table.setItem( i, j, QTableWidgetItem( str( var.iat[i, j] ) ) )
self.appt_table.resizeColumnsToContents()
def showDate(self, date):
now = QDate.currentDate()
select_date = self.cal.selectedDate()
if select_date < now:
pass
else:
string_date = str(select_date.toPyDate())
self.event_form(string_date)
def event_form(self, string_date):
with open('string_date.txt', 'w') as file:
file.write(string_date)
os.system( r"start /min python event_form.pyw" )

def paintEvent(self, e):
self.painter = QPainter( self )
self.painter.begin( self )
self.painter.setPen(QColor(75, 75, 75))
self.painter.drawLine(50, 230, 250, 230)
self.painter.drawLine(50, 340, 250, 340)
self.painter.end()
def exit(self):
self.close()
if __name__ == "__main__":
app = QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())
# event_form.pywimport sys
from datetime import datetime
from pymongo import MongoClient
from PyQt5.QtCore import QDate, Qt
from PyQt5.QtGui import (
QPen,
QFont,
QColor,
QBrush,
QPainter,
)
from PyQt5.QtWidgets import (
QLabel,
QWidget,
QLineEdit,
QTextEdit,
QCheckBox,
QComboBox,
QApplication,
)


client = MongoClient("localhost", 27017)
db = client["mydb"]
coll = db["appointments"]



class EventForm(QWidget):
def __init__(self):
super(EventForm, self).__init__()
self.initUI()

def initUI(self):
self.left = 1139
self.top = 253
self.width = 301
self.height = 370

self.setWindowFlags(Qt.FramelessWindowHint)
self.setGeometry(self.left,self.top,self.width,self.height)
self.setAutoFillBackground(True)
p = self.palette()
p.setColor(self.backgroundRole(), Qt.black)
self.setPalette(p)
qdim = "QPushButton {color: rgba(54, 136, 200, 250); background-color: black; }" segoe_9 = QFont( 'Segoe UI', 9 )
segoe_16 = QFont( "Segoe UI", 16 )
canda_10 = QFont( "Candalara", 10 )
canda_11 = QFont( "Candalara", 11 )
canda_12 = QFont( "Candalara", 12 )

times = [
'All Day','5:00 AM', '5:30 AM', '6:00 AM', '6:30 AM',
'7:00 AM', '7:30 AM', '8:00 AM', '8:30 AM', '9:00 AM',
'9:30 AM', '10:00 AM', '10:30 AM', '11:00 AM',
'11:30 AM', 'Noon', '12:30 PM', '1:00 PM', '1:30 PM',
'2:00 PM', '2:30 PM', '3:00 PM', '3:30 PM', '4:00 PM',
'4:30 PM', '5:00 PM', '5:30 PM', '6:00 PM',
]

with open('string_date.txt', "r") as file:
data = file.read()
day = str(num.strftime( '%A' ))
date = str(num.strftime('%m-%d-%Y'))
self.date_data = QLabel(self)
self.date_data.setGeometry( 0, 15, 301, 40 )
self.date_data.setStyleSheet( "QLabel {color: rgba(125,125,125,255); background-color: black;}" )
self.date_data.setFont( segoe_16 )
self.date_data.setAlignment(Qt.AlignCenter)
self.date_data.setText(day + " " + date)

self.time_label = QLabel(self)
self.time_label.setGeometry(15, 70, 80, 40)
self.time_label.setStyleSheet( "QLabel {color: rgba(125,125,125,255); background-color: black;}" )
self.time_label.setFont(canda_11)
self.time_label.setText("Time")

self.place_label = QLabel(self)
self.place_label.setGeometry(15, 115, 80, 40)
self.place_label.setStyleSheet( "QLabel {color: rgba(125,125,125,255); background-color: black;}" )
self.place_label.setFont(canda_11)
self.place_label.setText("Place")

self.note_label = QLabel(self)
self.note_label.setGeometry( 15, 160, 80, 40 )
self.note_label.setStyleSheet( "QLabel {color: rgba(125,125,125,255); background-color: black;}" )
self.note_label.setFont( canda_11 )
self.note_label.setText( "Note" )
self.time_cbox = QComboBox( self )
self.time_cbox.setGeometry( 70, 75, 100, 30 )
self.time_cbox.setStyleSheet( "QComboBox {color: rgba(125,125,125,255); background-color: black;}" )
self.time_cbox.setFont( canda_11 )
for time in times:
self.time_cbox.addItem(time)
self.time_cbox.currentIndexChanged.connect(self.
selectionchange)
self.place_edit = QLineEdit( self )
self.place_edit.setGeometry(70, 120, 215, 30 )
self.place_edit.setStyleSheet( "QLineEdit {color: rgba(125,125,125,255); background-color: rgba(29, 29, 29, 150); border: none;}" )
self.place_edit.setFont( canda_12 )

self.note_edit = QTextEdit(self)
self.note_edit.setGeometry( 70, 165, 215, 80 )
self.note_edit.setStyleSheet( "QTextEdit {color: rgba(125,125,125); background-color: rgba(29, 29, 29, 150); border: none;}" )
self.note_edit.setFont( canda_12 )
self.save = QPushButton(self)
self.save.setStyleSheet(qdim)
self.save.setFont(canda_10)
self.save.setText("SAVE")
self.save.setGeometry(120, 295, 60, 50)
self.save.clicked.connect(self.save)
self.exit = QPushButton(self)
self.exit.setStyleSheet(qdim)
self.exit.setFont(canda_10)
self.exit.setText("EXIT")
self.exit.setGeometry(210, 295, 60, 50)
self.exit.clicked.connect(self.exit)
self.sav-exit = QPushButton(self)
self.sav-exit.setStyleSheet(qdim)
self.sav-exit.setFont(canda_10)
self.sav-exit.setText("SAVE\nEXIT")
self.sav-exit.setGeometry(10, 240, 281, 90)
self.sav-exit.clicked.connect(self.save_exit)

def selectionchange(self):
self.place_edit.setFocus()
def paintEvent(self, e):
self.painter = QPainter( self )
self.painter.begin( self )
self.painter.setPen(QColor(75, 75, 75))
self.painter.drawLine(15, 65, 285, 65)
self.painter.drawLine(15, 270, 285, 270 )
self.painter.end()

def repeat(self):
date = self.date_data.text()[-10:]
time = self.time_cbox.currentText()
place = self.place_edit.text()
note = self.note_edit.toPlainText()
coll.insert_one({'date': date, "time": time, 'place': place, 'note': note})

def save(self):
data = self.repeat()
self.place_edit.clear()
self.note_edit.clear()

def save_exit(self):
data = self.repeat()
self.exit()

def exit(self):
self.close()



if __name__ == "__main__":
app = QApplication(sys.argv)
ex = EventForm()
ex.show()
sys.exit(app.exec_())

--

--

--

Retired military, Retired US Postal Service, Defender of the US Constitution from all enemies, foreign and domestic, Self-taught in python

Love podcasts or audiobooks? Learn on the go with our new app.

Recommended from Medium

Low Cost Build Monitor using Raspberry Pi

How I ‘edit’ my code

Terraform formatlist example

360° IT Check #17 — Google Cloud Carbon Footprint Reports, 25 Years of KDE, And More!

Building the Magical Data Science Box

Xamarin vs React Native - Which Framework is Best For App Development?

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
ZennDogg

ZennDogg

Retired military, Retired US Postal Service, Defender of the US Constitution from all enemies, foreign and domestic, Self-taught in python

More from Medium

Building a Python Chatbot — Part I

Organizing Images in Windows Using Python

How to send emails using Python and Office365 SMTP server

How to create a function in python to be used from the terminal