PyQt5 GUI编程
一.PyQt5简介
PyQt5是一个用于创建图形用户界面(GUI)应用程序的跨平台工具集,它将Qt库(广泛用于C++编程语言中创建丰富的GUI应用程序)的功能包装给Python使用者。PyQt5是由Riverbank Computing开发的,并且可以在所有主流操作系统上运行,包含Windows、macOS和Linux。
PyQt5包括了超过620个类和6000个函数和方法。这个框架支持包括SQL数据库、线程、Unicode、正则表达式、网络编程等高级功能。除了GUI功能外,PyQt5还允许用户访问Qt的模型/视图架构和QML(Qt Modeling Language),这是一种专门为创建动态和自定义用户界面而设计的语言。
二.环境搭建
1.终端使用pip安装PyQt5库
pip install -i https://pypi.tuna.tsinghua.edu.cn/simple PyQt5
2.如果出现Could not build wheels for PyQt5_sip, which is required to install pyproject.toml-based projects报错信息

3.先安装 Visual Studio 后再安装PyQt5即可,终端执行如下指令
wget https://aka.ms/vs/17/release/vs_BuildTools.exe -o vs_BuildTools.exe ; cmd /c vs_BuildTools.exe
勾选C++/CLI后安装就行

三.基本用法
1.PyQt5常见的模块
| QApplication | 这个类管理GUI应用程序的控制流和主要设置,并且是每个PyQt5应用程序中必须有的部分 |
| QWidget | 所有用户界面对象的基类。当你想创建一个自定义的窗口时,你会使用或者继承这个类 |
| QLabel | 用于展示文本或图片的类 |
| QtCore | 其他模块使用的核心非 GUI 类 |
| QAction | 用于处理菜单栏、工具栏或快捷键等的动作。 |
| QtSql | 使用 SQL 进行数据库集成的类 |
| QtXml | 处理 XML 的类 |
| QSlider | 滑动条,让用户通过滑动选择一个数值。 |
2.一个简单的窗口创建
import sys
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import QWidget, QLabel, QMessageBox, QApplication def windows():
# 创建一个 QApplication 类的应用程序对象
app = QApplication(sys.argv)
# 基于QWidget类声明窗口
w = QWidget()
# 添加一个QLabel对象,并将标签添加“helloworld”文本。
b = QLabel(w)
b.setText("Hello World!")
# 设置文本控件在窗口中的位置(x,y)
b.move(50, 50)
# 设置label控件的长和宽
b.resize(100,20)
# 设置字体样式大小
font = QFont()
font.setFamily("Arial") # 字体样式,中文英文都可(“楷体”)
font.setPointSize(20) # 字体大小
b.setFont(font)
# 通过 setGeometry() 方法定义窗口的大小和位置(x,y,w,h)
w.setGeometry(100, 100, 500, 1000)
# 设置窗口标题
w.setWindowTitle("PyQt5") # 显示窗口
w.show()
# 进入应用程序的主循环app.exec_()方法(窗口一直显示)
sys.exit(app.exec_()) if __name__ == '__main__':
windows()
备注写的很详细了,这里就不一一介绍每行代码的意思了。
3.窗口icon设置
import sys
from PyQt5.QtGui import *
from PyQt5.QtWidgets import QWidget, QApplication # 导入尽量用具体类,不用* class Window(QWidget):
def __init__(self, parent=None):
super().__init__(parent)
self.initUI()
self.setGeometry(100, 100, 500, 500)
self.setWindowTitle("PyQt5") # 设置icon
def initUI(self):
self.setWindowIcon(QIcon('./2.jpg')) # 设置窗口左上角icon def main():
app = QApplication(sys.argv)
ex = Window()
ex.show()
sys.exit(app.exec_()) if __name__ == '__main__':
main()
上述代码中,我们在initUI函数中,调用父类setWindowIcon()方法去设置窗口icon,在Window类中初始化时去调用initUI函数来实现设置icon。
4.QLabel控件
def qlabel(self):
font = QFont()
font.setFamily("Arial")
font.setPointSize(16)
label = QLabel(self)
label.setText("Hello World") # 设置文本
label.setFont(font) # 设置文本字体类型及大小
label.move(50, 20) # 控件在窗口的位置
这里和如上写法一致,在Window类中写一个qlabel函数,里面去调用QLabel,再在Window类中初始化时调用这个函数即可(使用QLabel模块时需提前导入该模块),我们来看下结果。

5.tips信息提示框
def tips(self):
# 创建一个按钮控件
btn = QPushButton('Button', self)
# 设置文本字体及大小
btn.setFont(QFont('SansSerif', 50))
# 设置tips
btn.setToolTip('This is a widget')
# 设置按钮在窗口的位置
btn.move(100, 100)
效果如下,鼠标悬浮在button上时,会出现tips信息弹框。

6.关闭二次确定弹框
主动关闭窗口(即点击窗口右上角X),弹出二次确定弹框,提示是否关闭。
import sys
from PyQt5.QtGui import *
from PyQt5.QtWidgets import QWidget, QApplication, QMessageBox, QDesktopWidget # 导入尽量用具体类,不用* class Window(QWidget):
def __init__(self, parent=None):
super().__init__(parent)
self.initUI()
self.setGeometry(100, 100, 500, 500)
self.setWindowTitle("PyQt5")
self.center() # 设置icon
def initUI(self):
self.setWindowIcon(QIcon('./2.jpg')) def closeEvent(self, event): # 关闭二次确定弹框
reply = QMessageBox.question(self, '是否关闭',
"Are you sure to quit?", QMessageBox.Yes, QMessageBox.No) if reply == QMessageBox.Yes:
event.accept() # 关闭窗口
else:
event.ignore() # 不关闭 def center(self): # 设置窗口居中
qt = self.frameGeometry() # 获取需要操作的窗口位置,长宽(即设置的setGeometry)
cp = QDesktopWidget().availableGeometry().center() # 获取电脑分辨率
qt.moveCenter(cp) # 获取电脑中间位置
self.move(qt.topLeft()) # 将窗口移动到中间位置 def main():
app = QApplication(sys.argv)
ex = Window()
ex.show()
sys.exit(app.exec_()) if __name__ == '__main__':
main()
上述代码中重写了父类中的closeEvent方法,通过QMessageBox.question()来获取用户行为,event.accept()来确定关闭窗口。

7.关闭窗口事件
def clos(self):
qbtn = QPushButton('Quit', self) # 创建一个按钮
qbtn.clicked.connect(QCoreApplication.instance().quit) # 回调关闭事件
qbtn.setToolTip("点击关闭窗口") # tips提示
qbtn.move(0, 0)
如下图效果,鼠标点击Quit按钮后窗口关闭,其效果和关闭按钮X一致。

8.菜单栏和工具栏
QMainWindow用于创建主应用程序窗口的类。它是 QWidget 的一个子类,提供了创建具有菜单栏、工具栏、状态栏等的主窗口所需的功能。
1)状态栏
import sys
from PyQt5.QtWidgets import QMainWindow, QApplication class Example(QMainWindow): def __init__(self):
super().__init__()
self.initUI() def initUI(self):
self.setGeometry(100, 100, 500, 500)
self.setWindowTitle('Statusbar')
self.statusBar().showMessage("状态栏") # 设置状态栏 if __name__ == '__main__':
app = QApplication(sys.argv)
ex = Example()
ex.show()
sys.exit(app.exec_())
状态栏的设置很简单,通过调用QMainWindow的statusBar()方法创建状态栏,showMessage()来设置状态栏显示的文本。

2)菜单栏
def bar(self):
action = QAction(QIcon('./2.jpg'), '登录', self) # 创建QAction实例
action.setShortcut('Ctrl+a') # 设置快捷键操作
action.setStatusTip('登录') # 状态栏提示,窗口的左下角出现,鼠标悬停在选项上会出现
action.triggered.connect(qApp.quit) # 点击事件后回调的方法(qApp.quit关闭窗口) menubar = self.menuBar() # 创建一个菜单栏
menu = menubar.addMenu('File') # 设置菜单栏tab menu.addAction(action) # 关联事件
用过menuBar()创建一个菜单栏,并添加addMenu()tab项,通过addAction()添加QAction行为动作,具体效果如下。

triggered.connect(qApp.quit)设置了触发动作后回调事件,即点击登录选项或快捷键Ctrl+A时会触发qApp.quit关闭窗口。上诉中我们只创建了一个菜单栏并只绑定了一个QAction如果想要多个菜单栏多个动作,可以创建多个addMenu(),下面看下具体实例。
def bar(self):
action = QAction(QIcon('./2.jpg'), '登录', self) # 创建QAction实例
action.setShortcut('Ctrl+a') # 设置快捷键操作
action.setStatusTip('登录') # 状态栏提示,窗口的左下角出现,鼠标悬停在选项上会出现
action.triggered.connect(qApp.quit) # 点击事件后回调的方法(qApp.quit关闭窗口) action1 = QAction(QIcon('./2.jpg'), '登录', self) # 创建QAction实例
action1.setShortcut('Ctrl+a') # 设置快捷键操作
action1.setStatusTip('退出') # 状态栏提示,窗口的左下角出现,鼠标悬停在选项上会出现
action1.triggered.connect(qApp.quit) # 点击事件后回调的方法(qApp.quit关闭窗口) menubar = self.menuBar() # 创建一个菜单栏
menu = menubar.addMenu('File') # 设置菜单栏tab
menubar1 = self.menuBar() # 创建一个菜单栏
menu1 = menubar1.addMenu('File1') # 设置菜单栏tab menu.addAction(action) # 关联事件
menu.addAction(action1) # 关联事件
3)子菜单栏
上面我们只是实现了一级菜单栏,那么在需求中要求创建二级,三级或者多级菜单,此时就需要用到QMenu()来创建下拉菜单栏了,我们先来看下二级菜单栏的创建。
# 创建子菜单
def bar_z(self):
menubar = self.menuBar() # 创建菜单栏
menu = menubar.addMenu('File') # 设置菜单栏tab newmenu = QMenu('一级下拉框', self) # 创建一个下拉菜单
impAct = QAction('二级目录', self) # 设置一个动作
impAct.triggered.connect(self.btn) # 点击事件后回调的方法
newmenu.addAction(impAct) # 添加动作到下菜单中 newact = QAction('一级目录', self) # 创建动作 menu.addAction(newact) # 添加动作到菜单栏
menu.addMenu(newmenu) # 添加下拉菜单到菜单栏 def btn(self):
# 创建一个按钮控件
btn = QPushButton('Button', self)
# btn.setGeometry(100, 100, 80, 30)
btn.move(100, 100)
btn.setToolTip("button")
btn.show()

如果我们想创建三级目录甚至更多级的目录,可以创建多个下拉菜单栏,并通过addMenu()添加进去,下面看下具体实现。
# 创建子菜单
def bar_z(self):
menubar = self.menuBar() # 创建菜单栏
menu = menubar.addMenu('File') # 设置菜单栏tab newmenu1 = QMenu('二级下拉框', self) # 创建一个下拉菜单
impAct1 = QAction('三级目录', self) # 设置一个动作
impAct1.triggered.connect(self.btn) # 点击事件后回调的方法
newmenu1.addAction(impAct1) # 添加动作到下菜单中 newmenu = QMenu('一级下拉框', self) # 创建一个下拉菜单
impAct = QAction('二级目录', self) # 设置一个动作
impAct.triggered.connect(self.btn) # 点击事件后回调的方法
newmenu.addAction(impAct) # 添加动作到下菜单中
newmenu.addMenu(newmenu1) # 添加下拉菜单栏到二级菜单下 newact = QAction('一级目录', self) # 创建动作 menu.addAction(newact) # 添加动作到菜单栏
menu.addMenu(newmenu) # 添加下拉菜单到菜单栏

4)带复选框的菜单
def bar_checkable(self):
menubar = self.menuBar()
bar_menu = menubar.addMenu('View') # 添加菜单栏
statact = QAction('复选框', self, checkable=True) # 创建一个可以勾选的动作
statact.setStatusTip('View statusbar')
statact.setChecked(True) # 设置默认选中
statact.triggered.connect(self.menu)
bar_menu.addAction(statact)
def menu(self, state):
if state:
print("勾选后执行的事件") # 勾选了
else:
print("取消勾选执行的事件") # 取消勾选
QAction()中,checkable=True表示可以勾选的动作。

5)右键栏
鼠标悬浮再窗口上,右击打开的菜单栏,此功能需要重写父类中contextMenuEvent()方法,看下代码演示。
def contextMenuEvent(self, event):
rightmenu = QMenu(self) # 创建一个下拉菜单
# 添加动作
d = rightmenu.addAction("打印")
q = rightmenu.addAction("退出")
ture = rightmenu.addAction("确定")
action = rightmenu.exec_(self.mapToGlobal(event.pos())) # exec_()显示菜单。获取动作行为
if action == d:
self.btn()
elif action == q:
qApp.quit() # 关闭窗口
else:
print("无确定内容")
6)工具栏
工具栏可以理解为是多个动作的集合,可以将多个QAction()添加展示出来。
def bar_tool(self): # 多个动作集合
action = QAction("工具1",self)
action2 = QAction("工具2",self)
action.setStatusTip("点击退出")
action.triggered.connect(qApp.quit)
toolbat = self.addToolBar("工具栏") # 创建一个工具栏
toolbat.addAction(action) # 将动作添加到工具栏
toolbat.addAction(action2) # 将动作添加到工具栏

7)主窗口显示
这个就不做过多介绍,在初始__init__中调用上诉几种方法即可,默认菜单栏在最顶部,添加的动作会更加调用的先后从左到右排列,工具栏默认在菜单栏下发,这里只看下效果截图。

9.页面布局
1)坐标布局

import sys from PyQt5.QtGui import QIcon
from PyQt5.QtWidgets import QLabel, QApplication, QWidget class Example(QWidget): def __init__(self):
super().__init__()
self.initUI() def initUI(self):
self.setGeometry(100, 100, 500, 500)
self.setWindowTitle('Statusbar')
q1 = QLabel("quit", self)
q2 = QLabel("quit2", self)
q3 = QLabel("quit3", self)
q1.move(20, 20) # 坐标布局
q2.move(20, 80) # 坐标布局
q3.move(20, 140) # 坐标布局 if __name__ == '__main__':
app = QApplication(sys.argv)
ex = Example()
ex.show()
sys.exit(app.exec_())
坐标布局
上述中通过move(x, y)方法来设置qlable的位置

2)界面比例布局

import sys from PyQt5.QtGui import QIcon
from PyQt5.QtWidgets import QApplication, QPushButton, QHBoxLayout, QWidget class Example(QWidget): def __init__(self):
super().__init__()
self.initUI()
self.button() def initUI(self):
self.setGeometry(100, 100, 500, 500)
self.setWindowTitle('Statusbar') def button(self): # 比例布局
ok = QPushButton("ok") # 创建三个按钮
cancel = QPushButton("cancel")
cancel1 = QPushButton("cancel1") hbox1 = QHBoxLayout() # 创建一个水平布局
hbox1.addWidget(ok) # 添加按钮到水平布局中
hbox1.addStretch(1) # 设置水平比例间距 hbox1.addWidget(cancel) # 添加按钮到水平布局中
hbox1.addStretch(1) # 设置水平比例间距
hbox1.addWidget(cancel1)
hbox1.addStretch(6) self.setLayout(hbox1) # 添加到布局器 if __name__ == '__main__':
app = QApplication(sys.argv)
ex = Example()
ex.show()
sys.exit(app.exec_())
水平布局
上面代码中通过QHBoxLayout() 创建一个水平布局,addWidget()将按钮添加到布局中,再通过addStretch()来设置比例间距,可以看到设置的比例为1:1:6


import sys from PyQt5.QtGui import QIcon
from PyQt5.QtWidgets import QApplication, QPushButton, QHBoxLayout, QVBoxLayout, QWidget class Example(QWidget): def __init__(self):
super().__init__()
self.initUI()
self.button() def initUI(self):
self.setGeometry(100, 100, 500, 500)
self.setWindowTitle('Statusbar') def button(self): # 比例布局
ok = QPushButton("ok") # 创建三个按钮
cancel = QPushButton("cancel")
cancel1 = QPushButton("cancel1") hbox = QHBoxLayout() # 创建一个水平布局
hbox.addStretch(1) # 设置水平比例间距(只设置一个stretch,会将按钮挤到最右侧。若stretch写在addWidget下面,则按钮会被寄到最左侧)
hbox.addWidget(ok) # 添加按钮到水平布局中
hbox.addWidget(cancel) vbox = QVBoxLayout() # 创建一个垂直布局
vbox.addStretch(1) # 设置垂直比例间距(只设置一个stretch,会将按钮挤到最下面。若stretch写在addlayout下面,则按钮会被寄到最下面)
vbox.addLayout(hbox) # 将刚刚创建的水平布局添加到垂直布局中 self.setLayout(vbox) # 将垂直布局加到布局器中(按钮位于页面右下角) if __name__ == '__main__':
app = QApplication(sys.argv)
ex = Example()
ex.show()
sys.exit(app.exec_())
垂直布局

3)栅格化布局

import sys from PyQt5.QtGui import QIcon
from PyQt5.QtWidgets import QApplication, QPushButton, QWidget, QGridLayout class Example(QWidget): def __init__(self):
super().__init__()
self.initUI()
self.Grid() def initUI(self):
self.setGeometry(100, 100, 500, 500)
self.setWindowTitle('Statusbar') def Grid(self): # 栅格化的按钮
grid = QGridLayout() # 创建一个栅格化布局
name = ["7", "8", "9", "/",
"4", "5", "6", "x",
"1", "2", "3", "-",
"清除", "0", ".", "="]
# 列表推导式
pos = [(x, y) for x in range(4) for y in range(4)]
for names, p in zip(name, pos): # 同时迭代两个序列
button = QPushButton(names) # 创建按钮
grid.setSpacing(10) # 设置各个单元格之间的间距
grid.addWidget(button, *p) # 添加到栅格化布局中
self.setLayout(grid) # 将栅格化布局加到布局器 if __name__ == '__main__':
app = QApplication(sys.argv)
ex = Example()
ex.show()
sys.exit(app.exec_())
栅格化布局
效果图

栅格化布局理论上也是通过坐标来定位的,通过列表推导式可到得到几个坐标(0,0)(0,1)(0,2)(1,0)(1,1)(1,2)..........,然后再通过坐标去逐个添加。
4)实例

import sys from PyQt5.QtGui import QIcon
from PyQt5.QtWidgets import QLabel, QApplication,QWidget, QGridLayout, \
QLineEdit, QTextEdit class Example(QWidget): def __init__(self):
super().__init__()
self.initUI()
self.input() def initUI(self):
self.setGeometry(100, 100, 500, 500)
self.setWindowTitle('Statusbar') def input(self):
grid = QGridLayout() # 设置标签
title = QLabel("title")
Author = QLabel("Author")
Review = QLabel("Review") # 设置输入框
titleEdit = QLineEdit() # 行编辑
authorEdit = QLineEdit()
reviewEdit = QTextEdit() # 文版编辑 grid.setSpacing(10) # 设置间距 grid.addWidget(title, 0, 0)
grid.addWidget(titleEdit, 0, 1)
grid.addWidget(Author, 1, 0)
grid.addWidget(authorEdit, 1, 1)
grid.addWidget(Review, 2, 0)
grid.addWidget(reviewEdit, 2, 1) self.setLayout(grid) if __name__ == '__main__':
app = QApplication(sys.argv)
ex = Example()
ex.show()
sys.exit(app.exec_())
实例
上述中实例通过QGridLayout()来将QLabel(), QLineEdit(行编辑) ,QTextEdit(文版编辑) 进行的整合使用,下面看下结果。

四.实例
以一个简单计算器功能为例,先来看下代码实现和效果展示

import sys from PyQt5.QtGui import QIcon
from PyQt5.QtWidgets import QApplication, QPushButton, QWidget, QGridLayout, \
QLineEdit class Example(QWidget): def __init__(self):
super().__init__()
self.initUI()
self.Grid() def initUI(self):
self.setGeometry(100, 100, 500, 500)
self.setWindowTitle('Statusbar') def Grid(self): # 栅格化的按钮
grid = QGridLayout()
hbox = QLineEdit()
grid.addWidget(hbox, 0, 0, 1, 4)
name = [
"7", "8", "9", "/",
"4", "5", "6", "*",
"1", "2", "3", "-",
"清除", "0", ".", "="]
# 列表推导式
pos = [(x, y) for x in range(1,5) for y in range(4)]
for names, p in zip(name, pos): # 同时迭代两个序列
if names == "":
continue
elif names == "hbox":
grid.addWidget(hbox, *p)
else:
button = QPushButton(names)
grid.addWidget(button, *p)
button.clicked.connect(lambda checked, btn_text=names: on_button_clicked(btn_text))
grid.setSpacing(10) # 设置各个单元格之间的间距 self.setLayout(grid) def on_button_clicked(btn_text):
try:
if btn_text == "清除":
hbox.clear()
elif btn_text == "=":
str_num = eval(hbox.text())
hbox.clear()
hbox.insert(str(str_num))
else:
hbox.insert(btn_text)
except:
hbox.insert("error") if __name__ == '__main__':
app = QApplication(sys.argv)
ex = Example()
ex.show()
sys.exit(app.exec_())
计算器

使用addWidget将输入框添加到栅格化布局中,后面无个参数分别表示:(添加对象,x位置,y位置,占据的单元格高度,占据的单元格宽度)。
grid.addWidget(hbox, 0, 0, 1, 4)
QLineEdit()几个常用的方法
hbox = QLineEdit()
hbox.setText("默认文案") # 设置默认文案
hbox.setPlaceholderText("暗文") # 当输入框内容为空时显示该文案
hbox.insert("243") # 添加
print(hbox.text()) # 获取框内容
hbox.clear() # 清空
五.打包
可参考:https://www.cnblogs.com/lihongtaoya/p/17349911.html
文章来源:https://www.cnblogs.com/lihongtaoya/ ,请勿转载
PyQt5 GUI编程的更多相关文章
- 用 eric6 与 PyQt5 实现python的极速GUI编程(系列01)--Hello world!
[题记] 我是一个菜鸟,这个系列是我的学习笔记. PyQt5 出来有一段时间了, PyQt5 较之 PyQt4 有一些变化,而网上流传的几乎都是 PyQt4 的教程,照搬的话大多会出错. eric6 ...
- Python gui编程pyQt5安装步骤t
Python gui编程pyQt5安装步骤 pip install PyQt5 Pip3 install PyQt5 https://riverbankco ...
- Python gui编程pyQt5安装步骤
Python gui编程pyQt5安装步骤 =============================== -m PyQt5.uic.pyuic $FileName$ -o $FileNameWit ...
- 用 eric6 与 PyQt5 实现python的极速GUI编程(35篇PyQT和200多篇Python)
[题记] 我是一个菜鸟,这个系列是我的学习笔记. PyQt5 出来有一段时间了, PyQt5 较之 PyQt4 有一些变化,而网上流传的几乎都是 PyQt4 的教程,照搬的话大多会出错. eric6 ...
- JAVA GUI编程学习笔记目录
2014年暑假JAVA GUI编程学习笔记目录 1.JAVA之GUI编程概述 2.JAVA之GUI编程布局 3.JAVA之GUI编程Frame窗口 4.JAVA之GUI编程事件监听机制 5.JAVA之 ...
- 1.JAVA之GUI编程概述
下列内容为本人看毕向东老师java视频教程学习笔记! JAVA GUI图形用户界面编程: Windows 操作系统提供两种操作方式: ...
- 2.JAVA之GUI编程布局
布局管理器 容器中的组件排放方式,就是布局 常见的布局管理器: **************************************************** 1.FlowLayout(流式 ...
- 3.JAVA之GUI编程Frame窗口
创建图形化界面思路: 1.创建frame窗体: 2.对窗体进行基本设置: 比如大小.位置.布局 3.定义组件: 4.将组件通过add方法添加到窗体中: 5.让窗体显示,通过setVisible(tur ...
- 4.JAVA之GUI编程事件监听机制
事件监听机制的特点: 1.事件源 2.事件 3.监听器 4.事件处理 事件源:就是awt包或者swing包中的那些图形用户界面组件.(如:按钮) 事件:每一个事件源都有自己特点有的对应事件和共性事件. ...
- 5.JAVA之GUI编程窗体事件
我们回顾下第三篇时的内容: 在3.JAVA之GUI编程Frame窗口中窗体是无法直接关闭的,想要关闭须进程管理器结束进程方式关掉. 现在我们就来解决下这个问题. ******************* ...
随机推荐
- 欢迎加入 DotNet NB 交流学习群
目录 起因 创建群组 群成员 技术交流 社区推广 社区前辈 欢迎加入 起因 自从2019年参加 .NET Conf China 大会之后,我创办了一个公众号 DotNet NB,内容主要是 关于 .N ...
- CF1878C Vasilije in Cacak 题解
题目传送门 简化题意 有 \(t\) 组询问,每次询问是否能从 \(1 \sim n\) 中选择 \(k\) 个数使得它们的和为 \(x\). 解法 考虑临界情况,从 \(1 \sim n\) 中选择 ...
- 49从零开始用Rust编写nginx,我竟然在同一个端口上绑定了多少IP
wmproxy wmproxy已用Rust实现http/https代理, socks5代理, 反向代理, 负载均衡, 静态文件服务器,websocket代理,四层TCP/UDP转发,内网穿透等,会将实 ...
- NC15033 小G有一个大树
题目链接 题目 题目描述 小G想要把自己家院子里的橘子树搬到家门口(QAQ..就当小G是大力水手吧) 可是小G是个平衡性灰常灰常差的人,他想找到一个这个橘子树的平衡点. 怎么描述这棵树呢...就把它看 ...
- 走出人生的舒适区,告别 CRUD
舒适区(Comfort zone),指的是一个人所处的一种环境的状态,和习惯的行动,人会在这种安乐窝的状态中感到舒适并且缺乏危机感. 工作中的舒适区 很多人工作也每天很累很辛苦,程序员每天都在加班加 ...
- aspell命令
aspell命令 aspell命令是一个交互式拼写检查器,其会扫描指定的文件或任何标准输入的文件,检查拼写错误,并允许交互式地纠正单词. 语法 aspell [options] command 参数 ...
- CF1398C Good Subarrays(写给我们萌新团体)
Good Subarrays 传送门: Good Subarrays - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 思路 暴力!!!!! 一如既往的暴力!!! 复杂度O(n^2) ...
- r0capture 原理分析
r0capture 是比较好用的抓包工具 仅限安卓平台,测试安卓7.8.9.10.11.12 可用 : 无视所有证书校验或绑定,不用考虑任何证书的事情: 通杀TCP/IP四层模型中的应用层中的全部协议 ...
- less变量书写及样式混入
定义变量 定义混入样式 变量及混入样式使用 样式文件中 ~@代表src
- 使用TLP对Linux系统进行充电保护
https://zhuanlan.zhihu.com/p/65546444 TLP:一个可以延长 Linux 笔记本电池寿命的高级电源管理工具 https://blog.csdn.net/zxw781 ...