PyQt5 is a cross-platform GUI toolkit, useful for creating interactive desktop applications. This is a keyword research tool we are talking about. We will use pytrends to get the keyword suggestions and regions of interest and pyqt5 as the framework to design the ui and emitting events.
There is a graph we are plotting in here, we will use pyqtgraph library for carving the graph.
Below are the libraries required for the application.
from functools import partial
import pandas as pd
from pytrends.request import TrendReq
import matplotlib.pyplot as plt
from pathlib import Path
from PyQt5.QtWidgets import *
from PyQt5 import QtCore, QtGui
from PyQt5.QtGui import *
from PyQt5.QtCore import *
import sys
import csv
from pyqtgraph import PlotWidget, plot
import pyqtgraph as pg
from os.path import exists
Next it is the driver code.
if __name__ == '__main__':
try:
# show the app icon on the taskbar
import ctypes
myappid = 'yourcompany.yourproduct.subproduct.version'
ctypes.windll.shell32.SetCurrentProcessExplicitAppUserModelID(myappid)
finally:
app = QApplication(sys.argv)
window = MainWindow()
window.setWindowFlags(window.windowFlags() &
QtCore.Qt.CustomizeWindowHint)
window.setWindowFlags(window.windowFlags() & ~
QtCore.Qt.WindowMinMaxButtonsHint)
window.show()
sys.exit(app.exec())
I have used the setWindowFlags on the main window instance to get rid of the resizable functionality of the main window.
Above is the main class which has all the member classes.
We will use _createMenubar function to create the main menu
The logic is clear we instantiate the QAction class and add action to the menu bar and connect openSearch function when clicked. Please ignore my naming convention, I know its really bad.
def openSearch(self):
self.leftarea()
file_exists = exists("searches.csv")
if file_exists == True:
self.downarea(self)
Open search is a window where we set the layout. The layout taken over here is a left area and a right area. The left area is where we search the items and right areas where is where we are showing the results.
For both the areas, we use QDockWidget.
def leftarea(self):
self.dock = QDockWidget("Search Keywords", self)
self.dock.setMaximumHeight(900)
self.dock.setMaximumWidth(500)
self.dock.setFloating(False)
# self.setCentralWidget(QTextEdit())
self.addDockWidget(Qt.DockWidgetArea.LeftDockWidgetArea, self.dock)
self.setWindowTitle("Keyword Searching Tool")
# Scroll Area Properties
search_form = QWidget()
layout = QFormLayout(search_form)
search_form.setLayout(layout)
self.search_term = QLineEdit(search_form)
self.search_term.setPlaceholderText("Enter a search term")
layout.addRow(self.search_term)
# icon = app.style().standardIcon(QStyle.SP_ArrowRight)
# action = self.search_term.addAction(icon, self.search_term.TrailingPosition)
self.search_term.textChanged.connect(
lambda param1, arg1=layout: self.onChanged(param1, arg1))
btn_search = QPushButton('Go', clicked=self.buttonClicked)
layout.addRow(btn_search)
self.dock.setWidget(search_form)
self.dock.move(20, 20)
self.dock.resize(900, 40)
self.dock.show()
So, below we are creating an instance of QDockWidget, setting up the maximum width and height.
Add the dock area to the dockwidget, and set a title.
self.dock = QDockWidget("Search Keywords", self)
self.dock.setMaximumHeight(900)
self.dock.setMaximumWidth(500)
self.dock.setFloating(False)
# self.setCentralWidget(QTextEdit())
self.addDockWidget(Qt.DockWidgetArea.LeftDockWidgetArea, self.dock)
self.setWindowTitle("Keyword Searching Tool")
So, next we create QWidget and QFormLayout and add the layout to the form.
search_form = QWidget()
layout = QFormLayout(search_form)
search_form.setLayout(layout)
self.search_term = QLineEdit(search_form)
self.search_term.setPlaceholderText("Enter a search term")
layout.addRow(self.search_term)
This is important.
self.search_term.textChanged.connect(
lambda param1, arg1=layout: self.onChanged(param1, arg1))
we are using texChanged event capturer to get the keyword suggestion from what the user write in the input field.
Let see what we are doing in that function.
def onChanged(self, param1, arg1):
self.show_edit = QLabel()
trends = TrendReq()
keyword = trends.suggestions(keyword=param1)
data = pd.DataFrame(keyword)
if data.head().empty:
self.show_edit.setText("No Matches Found")
arg1.addRow(self.show_edit)
self.show_edit.show()
if (len(keyword) != 0):
self.show_edit.setText(str(data.head()["title"][0]))
arg1.insertRow(data['title'].size, self.show_edit)
self.show_edit.show()
self.show_edit.mousePressEvent = self.buttonClicked
self.show_edit.mousePressEvent = partial(
self.buttonClicked, self.show_edit, str(data.head()["title"][0]))
else:
self.show_edit.setText("No Matches Found")
arg1.addRow(self.show_edit)
self.show_edit.show()
Here we are creating labels and adding a row under the area to see the keyword suggestion. we get the keyword suggestion from the TrendReq class from pytrends.
Here we are making the label clickable and when the a user clicks the desired label the right side area opens up with statistics table and graph.
We are handing this data gotten from pytrends in buttonClicked function.
Storing the data in the csv file and then calling the rightarea and downarea to see the statistics and graphs.
def downarea(self, dummmy):
self.dock = QDockWidget("See Statistics", self)
self.dock.setMaximumHeight(200)
self.dock.setMaximumWidth(900)
self.dock.setFloating(False)
# self.setCentralWidget(QTextEdit())
print("Show this")
self.addDockWidget(Qt.DockWidgetArea.RightDockWidgetArea, self.dock)
self.setWindowTitle("Keyword Searching Tool")
table = dict()
with open('searches.csv', 'r') as file:
reader = csv.reader(file)
for row in reader:
table[row[0]] = row[1]
tableList = []
for key, value in table.items():
tableList.append({
"Name": key,
"count": value
})
self.tableWidget = QTableWidget()
# # Row count
# Column count
self.tableWidget.setColumnCount(2)
self.tableWidget.setColumnWidth(0, 150)
self.tableWidget.setColumnWidth(1, 150)
# # self.tableWidget.setColumnWidth(2, 50)
self.tableWidget.setHorizontalHeaderLabels(tableList[0].keys())
self.tableWidget.setRowCount(len(tableList))
row = 0
for e in tableList:
print(e)
self.tableWidget.setItem(row, 0, QTableWidgetItem(e["Name"]))
self.tableWidget.setItem(row, 1, QTableWidgetItem(e["count"]))
row += 1
# Table will fit the screen horizontally
self.tableWidget.horizontalHeader().setStretchLastSection(True)
self.tableWidget.horizontalHeader().setSectionResizeMode(
QHeaderView.Stretch)
self.dock.setWidget(self.tableWidget)
self.dock.move(20, 20)
self.dock.resize(90, 40)
self.dock.show()
The above function is handling the logic of reading the csv file and displaying the data in the table. There are some common configuration that is universal. only thing you have to process is displaying the data in list of dictionaries formation to be able to use this configuration.
The code for the graph is below.
def rightarea(self, dummmy):
self.dock = QDockWidget("See Statistics", self)
self.dock.setMaximumHeight(900)
self.dock.setMaximumWidth(900)
self.dock.setFloating(False)
# self.setCentralWidget(QTextEdit())
print("Show this")
self.addDockWidget(Qt.DockWidgetArea.RightDockWidgetArea, self.dock)
self.setWindowTitle("Keyword Searching Tool")
y1 = []
# create horizontal list i.e x-axis
x = []
with open('searches.csv', 'r') as file:
reader = csv.reader(file)
for row in reader:
x.append(row[0])
y1.append(int(row[1]))
print(y1, x)
# creating a pyqtgraph plot window
window = pg.plot()
window.setBackground("w")
xval = list(range(1, len(x)+1))
ticks = []
for i, item in enumerate(x):
ticks.append((xval[i], item))
ticks = [ticks]
bargraph = pg.BarGraphItem(x=xval, height=y1, width=0.5)
window.addItem(bargraph)
ax = window.getAxis('bottom')
ax.setTicks(ticks)
self.dock.setWidget(window)
self.dock.move(20, 20)
self.dock.resize(90, 40)
self.dock.show()
So with this code in place you can just run the app and see the action. You can find the complete form on my github link.
In case of any queries you can find me using my email address : pro_chunks@pallavy.com
Hope this helps!