做为一名码友,我喜欢diy各种QT软件,以前用通用的订单管理软件,总是有太多不需要的功能,很碍眼,最终,还是没忍住,自己写了一个简单实用,且还算美观的订单管理系统。
动图如下,如果喜欢,我可以分享原码,也打包好了exe。
好开始,希望给爱好编程的你提供一些参考
一、先上登录页面,原码在下面
二、新增订单,原码在下面
三、搜索订单,请注意下面的统计变化-原码在下面
四、修改订单-原码在下面
五、删除订单-原码在下面
import sys
from PyQt5.QtCore import Qt,QPoint
from PyQt5.QtGui import QMouseEvent
from PyQt5.QtWidgets import QApplication, QMainWindow, QDesktopWidget
from kw_login import Ui_MainWindow
from main_kiwi07282014 import MainWindow
class LoginWindow(QMainWindow,Ui_MainWindow):
def __init__(self):
super().__init__()
self._endPos = None
self._startPos = None
self._tracking = None
self.setWindowFlags(Qt.FramelessWindowHint | Qt.WindowStaysOnTopHint)
self.setAttribute(Qt.WA_TranslucentBackground)
self.mainwindow = None
self.setupUi(self)
self.retranslateUi(self)
self.statusBar().setSizeGripEnabled(False)
self.pushButton_login.clicked.connect(self.login)
def mouseMoveEvent(self, e: QMouseEvent): # 重写移动事件
if self._tracking:
self._endPos = e.pos() - self._startPos
self.move(self.pos() + self._endPos)
def mousePressEvent(self, e: QMouseEvent):
if e.button() == Qt.LeftButton:
self._startPos = QPoint(e.x(), e.y())
self._tracking = True
def mouseReleaseEvent(self, e: QMouseEvent):
if e.button() == Qt.LeftButton:
self._tracking = False
self._startPos = None
self._endPos = None
def login(self):
if self.lineEdit_usrname.text() == 'syh' and self.lineEdit_passwd.text() == '123':
print('正确登录')
loginwindow.close()
self.mainwindow = MainWindow()
self.mainwindow.show()
else:
print('用户名或密码错误')
self.lineEdit_usrname.clear()
self.lineEdit_usrname.setPlaceholderText('请输入正确的用户名')
self.lineEdit_usrname.setStyleSheet("background-color: rgb(255, 0, 0);color: rgb(255, 255, 255);font: 14pt '黑体';")
self.lineEdit_passwd.clear()
self.lineEdit_passwd.setPlaceholderText('请输入正确的密码')
self.lineEdit_passwd.setStyleSheet(
"background-color: rgb(255, 0, 0);color: rgb(255, 255, 255);font: 14pt '黑体';")
def center(self):
# 获取屏幕坐标系
screen = QDesktopWidget().screenGeometry()
# 获取窗口坐标系
size = self.geometry()
newLeft = (screen.width() - size.width()) / 2
newTop = (screen.height() - size.height()) / 2
self.move(int(newLeft), int(newTop)) # 移动窗口,需将坐标转换为整数
if __name__ == '__main__':
app = QApplication(sys.argv)
loginwindow = LoginWindow()
loginwindow.show()
sys.exit(app.exec_())
from PyQt5.QtGui import QIcon
from PyQt5.QtWidgets import QMainWindow, QMenu, QAbstractItemView, QDesktopWidget, QTableWidgetItem
from PyQt5.QtCore import Qt, QPoint, QEvent
from filter import filter_excel_by_multiple_columns
class MainWindow(QMainWindow,Ui_MainWindow):
def __init__(self):
super().__init__()
self._endPos = None
self._startPos = None
self._tracking = None
self.setupUi(self)
self.retranslateUi(self)
self.setWindowTitle('kiwi赚米工具-主界面')
icon = QIcon('logo.png')
self.setWindowIcon(icon)
self.center()
self.title = ''
self.message = ''
self.new_window = None
self.edit_window = None
# 锁定qtableweget的编辑功能
self.tableWidget.setEditTriggers(QAbstractItemView.NoEditTriggers) # 禁用编辑
self.tableWidget.setSelectionBehavior(QAbstractItemView.SelectRows) #设置选定行
self.tableWidget.setContextMenuPolicy(Qt.CustomContextMenu)
self.tableWidget.customContextMenuRequested.connect(self.show_custom_menu) # 连接信号到槽函数
self.excle_path = r'.\订单存放\kiwi-订单.xlsx'
self.out_put_path = r'.\导出的地址'
self.data = ''
# 默认展示全部
self.reset()
self.pushButton_search.clicked.connect(self.search)
self.pushButton_reset.clicked.connect(self.reset)
self.pushButton_out.clicked.connect(self.out_put)
self.pushButton_in.clicked.connect(self.creat_dingdan)
self.pushButton_today.clicked.connect(self.today)
self.pushButton_yestody.clicked.connect(self.yestoday)
self.pushButton_sevenday.clicked.connect(self.sevenday)
def show_custom_menu(self, pos):
'''qtablewidget按按钮设置'''
menu = QMenu()
item1 = menu.addAction('编辑')
item2 = menu.addAction('删除')
screen_pos = self.tableWidget.mapToGlobal(pos)
action = menu.exec(screen_pos)
if action == item1:
self.edit_dingdan()
print('选择了第一个菜单项')
elif action == item2:
self.del_dingdan()
print('选择了第二个菜单项')
def get_selected_row_content(self):
'''获取选定行内容'''
selected_items = self.tableWidget.selectedItems()
row_contents = []
if selected_items:
row = selected_items[0].row()
for column in range(self.tableWidget.columnCount()):
item = self.tableWidget.item(row, column)
if item:
row_contents.append(item.text())
print(f'选种单元格的内容为{row_contents}')
return row_contents
def convert_list_to_dict(self,input_list):
output_dict = {
'订单编号': input_list[1],
'品种': input_list[2],
'规格(斤)': input_list[3],
'价格(元)': input_list[4],
'数量': input_list[5],
'付款状态(Y/N)': input_list[6],
'下单日期': input_list[7],
'客户标识': input_list[8],
'地址': input_list[9],
'快递单号': input_list[10],
'备注': input_list[12],
}
return output_dict
def center(self):
# 获取屏幕坐标系
screen = QDesktopWidget().screenGeometry()
# 获取窗口坐标系
size = self.geometry()
newLeft = (screen.width() - size.width()) / 2
newTop = (screen.height() - size.height()) / 2
self.move(int(newLeft), int(newTop)) # 移动窗口,需将坐标转换为整数
def filter(self):
reciver = self.lineEdit_reciver.text()
buyer = self.lineEdit_buyer.text()
shuiguo = self.comboBox_shuiguo.currentText()
fukuan = self.comboBox_fukuan.currentText()
if self.dateEdit_datestart.text() != self.dateEdit_dateend.text():
xiadan_start = self.dateEdit_datestart.text()
xiadan_end = self.dateEdit_dateend.text()
xiadan_start = xiadan_start,xiadan_end
xiadan_start = list(xiadan_start)
else:
xiadan_start = self.dateEdit_datestart.text()
kuaididanhao = str(self.lineEdit_kuaidi.text())
conditions = {'地址': reciver,
'客户标识':buyer,
'品种':shuiguo,
'付款状态(Y/N)':fukuan,
'下单日期':xiadan_start,
'快递单号':kuaididanhao
}
conditions = remove_empty_values(conditions)
print(conditions)
return conditions
def search(self):
try:
conditions = self.filter()
self.data = filter_excel_by_multiple_columns(self.excle_path, conditions)
self.populate_table(self.data[0])
data_fomat_type = self.format_dictionary(self.data[1])
self.textEdit.setText(data_fomat_type)
data_fomat_sum = self.format_dictionary_sum(self.data[2])
self.textEdit_2.setText(data_fomat_sum)
except Exception as e:
print(e)
def populate_table(self, data):
"""
将数据填充到 QTableWidget 中,显示 Excel 的列名且去掉行数字
参数:
订单存放 (DataFrame): 要填充的数据
"""
# 设置表格的列数
self.tableWidget.setColumnCount(data.shape[1])
# 获取列名并设置
column_names = data.columns
for col in range(data.shape[1]):
item = QTableWidgetItem(str(column_names[col]))
self.tableWidget.setHorizontalHeaderItem(col, item)
# 隐藏行数字(行索引)
self.tableWidget.verticalHeader().setVisible(False)
# 填充数据
self.tableWidget.setRowCount(data.shape[0])
for col_index, col_name in enumerate(column_names):
if col_name == '地址': # 只处理地址列
self.tableWidget.setColumnWidth(col_index, 100 * self.fontMetrics().width(' ')) # 设置地址列宽度为 55 个字符宽度
elif col_name == '序号': # 只处理地址列
self.tableWidget.setColumnWidth(col_index, 7 * self.fontMetrics().width(' ')) # 设置地址列宽度为 55 个字符宽度
elif col_name == '订单编号': # 只处理订单编号列
self.tableWidget.setColumnWidth(col_index, 22 * self.fontMetrics().width(' ')) # 设置订单编号列宽度
elif col_name == '品种': # 只处理地址列
self.tableWidget.setColumnWidth(col_index, 7 * self.fontMetrics().width(' ')) # 设置地址列宽度为 55 个字符宽度
elif col_name == '规格(斤)': # 只处理地址列
self.tableWidget.setColumnWidth(col_index, 15 * self.fontMetrics().width(' ')) # 设置地址列宽度为 55 个字符宽度
elif col_name == '价格(元)': # 只处理地址列
self.tableWidget.setColumnWidth(col_index, 15 * self.fontMetrics().width(' ')) # 设置地址列宽度为 55 个字符宽度
elif col_name == '数量': # 只处理地址列
self.tableWidget.setColumnWidth(col_index, 7 * self.fontMetrics().width(' ')) # 设置地址列宽度为 55 个字符宽度
elif col_name == '付款状态(Y/N)': # 只处理地址列
self.tableWidget.setColumnWidth(col_index, 21 * self.fontMetrics().width(' ')) # 设置地址列宽度为 55 个字符宽度
elif col_name == '下单日期': # 只处理地址列
self.tableWidget.setColumnWidth(col_index, 17 * self.fontMetrics().width(' ')) # 设置地址列宽度为 55 个字符宽度
elif col_name == '快递单号': # 只处理订单编号列
self.tableWidget.setColumnWidth(col_index, 32 * self.fontMetrics().width(' ')) # 设置订单编号列宽度
elif col_name == '备注': # 只处理订单编号列
self.tableWidget.setColumnWidth(col_index, 32 * self.fontMetrics().width(' ')) # 设置订单编号列宽度
for row in range(data.shape[0]):
if col_name == '地址': # 只处理地址列
item = QTableWidgetItem(str(data.iat[row, col_index]))
item.setTextAlignment(Qt.AlignLeft) # 设置左对齐
self.tableWidget.setItem(row, col_index, item)
elif pd.api.types.is_datetime64_any_dtype(data[col_name]): # 判断是否为日期列
date_value = data.iat[row, col_index]
if not pd.isnull(date_value): # 处理非空值
date_item = QTableWidgetItem(pd.to_datetime(date_value).strftime('%Y-%m-%d'))
else: # 处理空值
date_item = QTableWidgetItem('')
date_item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
self.tableWidget.setItem(row, col_index, date_item)
else: # 非日期列
item = QTableWidgetItem(str(data.iat[row, col_index]))
item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
self.tableWidget.setItem(row, col_index, item)
def reset(self):
try:
conditions = {}
self.lineEdit_reciver.clear()
self.lineEdit_buyer.clear()
self.lineEdit_kuaidi.clear()
self.comboBox_shuiguo.setCurrentIndex(-1)
self.comboBox_fukuan.setCurrentIndex(0)
self.data = filter_excel_by_multiple_columns(self.excle_path, conditions)
self.populate_table(self.data[0])
today = datetime.date.today()
self.dateEdit_datestart.setDate(QDate(2023, 8, 23))
self.dateEdit_dateend.setDate(today)
data_fomat_type = self.format_dictionary(self.data[1])
self.textEdit.setText(data_fomat_type)
data_fomat_sum = self.format_dictionary_sum(self.data[2])
self.textEdit_2.setText(data_fomat_sum)
except Exception as e:
print(e)
def out_put(self):
try:
if not self.data[0].empty:
self.message = '导出成功'
self.title = '导出成功弹窗'
self.address_txt(df=self.data[0])
self.showPopup()
else:
self.message = '导出失败无内容'
self.title = '导出失败弹窗'
self.showPopup()
print('无内容')
except Exception as e:
print(e)
def showPopup(self):
msg = QMessageBox(self) # 设置父窗口为当前窗口
msg.setIcon(QMessageBox.Information)
msg.setText(self.message)
msg.setWindowTitle(self.title)
msg.exec_()
def address_txt(self,df):
try:
# 获取地址列的内容
addresses = df['地址']
# 获取当前时间并格式化
now = datetime.datetime.now()
formatted_now = now.strftime("%Y%m%d%H%M%S")
# 写入 txt 文件
with open(fr'{self.out_put_path}\地址_{formatted_now}.txt', 'w') as f:
for address in addresses:
f.write(address + '\n')
except Exception as e:
print(e)
def today(self):
print('今天')
today = datetime.date.today()
self.dateEdit_datestart.setDate(today)
self.dateEdit_dateend.setDate(today)
def yestoday(self):
print('昨天')
today = datetime.date.today()
yesterday = today - datetime.timedelta(days=1)
self.dateEdit_datestart.setDate(yesterday)
self.dateEdit_dateend.setDate(yesterday)
pass
def sevenday(self):
print('近7天')
today = datetime.date.today()
sevenday = today - datetime.timedelta(days=6)
self.dateEdit_datestart.setDate(sevenday)
self.dateEdit_dateend.setDate(today)
def format_dictionary(self,dictionary):
result = ""
for key, value in dictionary.items():
variety, size = key
result += f"{variety}{size}斤 = {value}箱; "
return result
def format_dictionary_sum(self,dictionary):
result = ""
for key, value in dictionary.items():
result += f"{key} = {value}斤; "
return result
def creat_dingdan(self):
print(self.new_window)
try:
self.new_window.destroy()
self.edit_window.destroy()
except Exception as e:
print(e)
self.new_window = CreatWindow(self) # 保存为实例属性
self.new_window.show()
self.alignWindows(window=self.new_window) # 调用对齐窗口的方法
self.new_window.trigger_action_signal.connect(self.reset)
if not self.isMaximized():
self.new_window.trigger_action_signal_move.connect(self.center)
def edit_dingdan(self):
try:
self.new_window.destroy()
self.edit_window.destroy()
except Exception as e:
print(e)
edit_info = self.get_selected_row_content()
print(edit_info)
edit_dic = self.convert_list_to_dict(edit_info)
try:
self.edit_window = EditWindow(self,edit_dic=edit_dic) # 保存为实例属性
self.edit_window.show()
if not self.isMaximized():
self.alignWindows(self.edit_window) # 调用对齐窗口的方法
self.edit_window.trigger_action_signal.connect(self.reset)
if not self.isMaximized():
self.edit_window.trigger_action_signal_move.connect(self.center)
except Exception as e:
print(e)
def del_dingdan(self):
msgBox = QMessageBox(self)
msgBox.setWindowTitle("删除提示")
msgBox.setText("您确定要继续吗?\n删除将不可恢复")
msgBox.setStandardButtons(QMessageBox.Ok | QMessageBox.Cancel)
msgBox.button(QMessageBox.Ok).setText("确认")
msgBox.button(QMessageBox.Cancel).setText("取消")
result = msgBox.exec_()
if result == QMessageBox.Ok:
print("用户点击了确定,继续操作")
edit_info = self.get_selected_row_content()
print(edit_info)
edit_dic = self.convert_list_to_dict(edit_info)
print(f'del_dingdan删除{edit_dic}')
# 弹出确认框
try:
del_dingdana(data=edit_dic,file_path=self.excle_path) # 保存为实例属性
self.reset()
except Exception as e:
print(e)
def alignWindows(self,window = None): # 封装的对齐窗口方法
if window: # 直接使用保存的实例属性
if not self.isMaximized():
# 新窗口的初始位置,使其与原窗口右边对齐且上边缘在同一直线
window.move(self.x() + self.width(), self.y())
# 计算组合图形的位置调整量,并进行整数转换
screen = QDesktopWidget().screenGeometry()
total_width = self.width() + window.width()
total_height = max(self.height(), window.height())
center_x = int(screen.width() / 2)
center_y = int(screen.height() / 2)
x_adjust = int(center_x - (self.x() + total_width / 2))
y_adjust = int(center_y - (self.y() + total_height / 2))
# 移动组合图形
self.move(self.x()+1 + x_adjust, self.y()-22+ y_adjust)
window.move(window.x() + x_adjust-9, window.y() + y_adjust)
def del_pop(self):
result = QMessageBox.question(self, '提示', '您确定要继续吗?', QMessageBox.Ok | QMessageBox.Cancel)
if result == QMessageBox.Ok:
print("用户点击了确定,继续操作")
else:
print("用户点击了取消,停止操作")
def cant_del_pop(self):
msg = QMessageBox(self) # 设置父窗口为当前窗口
msg.setIcon(QMessageBox.Information)
msg.setText(self.message)
msg.setWindowTitle(self.title)
msg.exec_()
if __name__ == '__main__':
from 猕猴桃订单管理.creat_new_main import *
app = QApplication(sys.argv)
myshow = MainWindow()
myshow.show()
sys.exit(app.exec_())
如果需要打包文件,请关注后续更新