实现一个用PyQt写的格式化一个文本的小工具

一款使用Python和PyQt开发的文本处理工具,旨在快速在大量文本行的前后或中间插入特定字符,提升文本编辑效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1 本工具使用python的PyQt编写的,第一次尝试,所以暂时将代码和界面写到一起,后期应该会分开。

2 实现的功能是  例如  AA  BB  要在这两个字符前后,中间,添加特定的字符,如果只有一行,还是手动比较快,但是行数过多之后就比较麻烦了,因此编写此工具作为第一版。

import sys

from PyQt5.QtCore import Qt, pyqtSignal
from PyQt5.QtGui import QIcon, QTextCursor
from PyQt5.QtWidgets import (QMainWindow, QApplication, QAction, qApp, QHBoxLayout, QVBoxLayout, QPushButton,
                             QFrame, QTextEdit, QFileDialog, QSplitter, QWidget, QDesktopWidget, QCheckBox, QMessageBox,
                             QScrollArea, QLabel, QLineEdit, QGridLayout)


class NeLa2(QMainWindow):
    textsignal = pyqtSignal(str)  # 信号定义为类属性

    def __init__(self):
        super().__init__()

        self.v_splitter = QSplitter(Qt.Vertical)
        self.h_splitter = QSplitter(Qt.Horizontal)
        self.buttom = QFrame(self)
        self.all_box = QHBoxLayout(self)  # 总体布局
        self.topright = QFrame(self)  # 右边控件
        self.topleft = QFrame(self)  # 左边控件

        self.frm = QFrame(self)  # 程序的总体面板
        self.lbl = QLabel()  # 底部显示面板

        self.s = SecondWindow()  # 子面板
        self.textsignal.connect(self.s.showSelect)  # 连接信号和槽函数
        self.initUI()

    def initUI(self):
        global text_edit
        text_edit = QTextEdit()  # 文本框

        self.initMenu()  # 初始化菜单栏
        self.initLayout()  # 初始化布局

        self.lbl.setFrameShape(QLabel.StyledPanel)
        self.lbl.setFixedSize(835, 30)

        buttom_hbox = QHBoxLayout(self)  # 下,底部显示面板布局
        buttom_hbox.addWidget(self.lbl)
        self.buttom.setLayout(buttom_hbox)

    # 初始化布局
    def initLayout(self):

        self.topleft = QFrame(self)
        self.topleft.setFrameShape(QFrame.StyledPanel)

        self.topright = QFrame(self)
        self.topright.setFrameShape(QFrame.StyledPanel)

        self.buttom.setFrameShape(QFrame.StyledPanel)

        self.h_splitter.addWidget(self.topleft)
        self.h_splitter.addWidget(self.topright)

        self.v_splitter.addWidget(self.h_splitter)
        self.v_splitter.addWidget(self.buttom)

        self.all_box.addWidget(self.v_splitter)

        self.topright.setGeometry(0, 20, 800, 780)  # 顶部右边,使得左边范围变小
        self.h_splitter.setGeometry(0, 20, 700, 600)  # 是的下边范围变小
        self.frm.setGeometry(0, 20, 880, 760)
        self.frm.setLayout(self.all_box)

        # self.setGeometry(500, 200, 880, 780)  # 距左,距上,宽,高
        self.setFixedSize(880, 780)
        self.show()
        self.center()

    # 初始化菜单栏
    def initMenu(self):
        self.statusBar()

        # 退出菜单
        exitAction = QAction(QIcon('../img/exit.jpg'), 'Exit', self)
        exitAction.setShortcut('Ctrl+Q')  # 快捷键
        exitAction.setStatusTip('Exit Tools')
        exitAction.triggered.connect(qApp.quit)

        # 打开文件菜单
        open_file = QAction(QIcon('../img/exit.jpg'), 'Open...', self)
        open_file.setShortcut('Ctrl+O')
        open_file.setStatusTip('Open New File')
        open_file.triggered.connect(self.show_dialog)

        # 编辑菜单
        editAction = QAction(QIcon('../img/exit.jpg'), 'Edit', self)
        editAction.setShortcut('Ctrl+E')  # 快捷键
        editAction.setStatusTip('Edit Tools')
        editAction.triggered.connect(self.editDialog)
        # 设置菜单
        menubar = self.menuBar()
        filemenu = menubar.addMenu('&File')
        filemenu.addAction(exitAction)
        filemenu.addAction(open_file)

        editmenu = menubar.addMenu('&Edit')
        editmenu.addAction(editAction)
        self.setWindowTitle('Main ')

    # 显示到中间
    def center(self):
        # screen = QDesktopWidget().screenGeometry()
        # size = self.geometry()
        # self.move((screen.width() - size.width()) / 2, (screen.height() - size.height()) / 2)

        qr = self.frameGeometry()
        cp = QDesktopWidget().availableGeometry().center()
        qr.moveCenter(cp)
        self.move(qr.x(), qr.y())

    # 编辑控件
    def editDialog(self):

        btnJSP = QPushButton(self)
        btnJava = QPushButton(self)
        btnJava.clicked.connect(self.showText)

        btnJava.setText('Java')
        btnJSP.setText('Jsp')

        vbox = QVBoxLayout(self)
        vbox.addWidget(btnJava)
        vbox.addWidget(btnJSP)
        vbox.addStretch(1)

        lhbox = QHBoxLayout(self)
        lhbox.addStretch(1)  # 延伸因子,均分布局
        lhbox.addLayout(vbox)

        rhbox = QHBoxLayout(self)
        rhbox.addWidget(text_edit)

        text_edit.selectionChanged.connect(self.selectLines)  # 连接文本选中事件

        self.topleft.setLayout(lhbox)  # 添加按钮控件
        self.topright.setLayout(rhbox)  # 添加编辑文本控件

    # open file
    def show_dialog(self):
        fname = QFileDialog.getOpenFileName(self, 'Open File', '/home')

        if fname[0]:
            f = open(fname[0], 'r')

            with f:
                data = f.read()
                text_edit.setText(data)

    # 获取内容显示到子窗口
    def showText(self):
        content = text_edit.toPlainText()
        self.sendEditText(content)
        self.s.click()

    def sendEditText(self, content):
        self.textsignal.emit(content)  # 发送信号

    # 选中行
    def selectLines(self):
        # print('文本信息')
        # print(text_edit.toPlainText())

        try:
            cursor = text_edit.textCursor()
            col_num = '列位置:{}'.format(QTextCursor.columnNumber(cursor))
            block_num = 'row:{}'.format(QTextCursor.blockNumber(cursor) + 1)
            start = '光标是否在开始位置:{}'.format(QTextCursor.atStart(cursor))
            end = '光标是否在结束位置:{}'.format(QTextCursor.atEnd(cursor))
            sel_str = str(QTextCursor.selection(cursor).toPlainText())
            nsel_str = '选择的文本:{}'.format(QTextCursor.selectedText(cursor))

            if sel_str != '':
                nexline = str(sel_str.count('\n')) + ' line break'
                l = len(sel_str)
                if l == 1:
                    len_str = '1 char'
                elif l > 1:
                    len_str = str(len(sel_str)) + 'chars'
                self.lbl.setText(col_num + '   ' + block_num + '   ' + len_str + '   ' + nexline)

            # print(col_num)
            # print(block_num)
            # print(start)
            # print(end)
            # print(sel_str)  # 带有格式的文本
            # print(nsel_str)  # 不带有格式的文本
            # print(sel_str.count('\n'))  # 几个换行

        except Exception as e:
            print(e)

    # 重新显示
    def reShowText(self):
        if len(l) == 0:
            return
        try:
            text_edit.clear()
            for x in l:
                text_edit.append(x)
        except Exception as e:
            print(e)


class SecondWindow(QWidget):
    listsignal = pyqtSignal(list)  # 信号定义为类属性

    def __init__(self):
        super().__init__()
        self.label = QLabel()
        self.top = QFrame(self)
        self.buttom = QFrame(self)
        self.top_edit = QTextEdit()
        self.scroll = QScrollArea()

        self.vehbox = QVBoxLayout()

        self.listsignal.connect(NeLa2.reShowText)  # 连接信号和槽函数
        self.initUI()

    def initUI(self):
        # 功能按钮
        selectAllButton = QPushButton('Select All')
        selectAllButton.clicked.connect(self.selectAll)
        deselectAllButton = QPushButton('Deselect All')
        deselectAllButton.clicked.connect(self.deselectAll)

        AnalysisButton = QPushButton('Analysis')
        AnalysisButton.clicked.connect(self.analyText)

        # 分析后显示控件
        global anaLabel  # 定义为全局变量
        anaLabel = QLabel()

        okButton = QPushButton('OK')
        okButton.clicked.connect(self.sendText)
        cancelButton = QPushButton('Cancel')
        cancelButton.clicked.connect(self.close)  # 直接触发窗口的close方法,此方法会调用closeEvent

        # 分析文本框title
        line_edit_title = QLabel('表达式:')
        # 分析文本输入框
        global line_edit
        line_edit = QLineEdit()
        global line_regular

        # 键title
        line_key_title = QLabel('键:')
        # 键
        global line_key
        line_key = QLineEdit()
        # 值title
        line_value_title = QLabel('值:')
        # 值
        global line_value
        line_value = QLineEdit()

        # 底部
        hbox = QHBoxLayout()
        hbox.addStretch(1)
        hbox.addWidget(okButton)
        hbox.addWidget(cancelButton)

        grid = QGridLayout()
        grid.setSpacing(10)
        grid.addWidget(line_edit_title, 2, 1)
        grid.addWidget(line_edit, 2, 2, 1, 4)

        grid.addWidget(line_key_title, 3, 1)
        grid.addWidget(line_key, 3, 2)
        grid.addWidget(line_value_title, 3, 3)
        grid.addWidget(line_value, 3, 4)
        grid.addWidget(AnalysisButton, 3, 5)

        grid.addWidget(anaLabel, 4, 1)

        hbox2 = QHBoxLayout()
        hbox2.addWidget(selectAllButton)
        hbox2.addWidget(deselectAllButton)
        hbox2.addStretch(1)

        # 下半部分
        vbox = QVBoxLayout()
        vbox.addLayout(hbox2)
        vbox.addLayout(grid)
        vbox.addStretch(1)
        vbox.addLayout(hbox)

        # 上半部分
        tbox = QVBoxLayout()
        tbox.addWidget(self.scroll)

        self.top.setLayout(tbox)
        self.buttom.setLayout(vbox)

        self.top.setFrameShape(QFrame.StyledPanel)
        self.buttom.setFrameShape(QFrame.StyledPanel)
        self.top.setGeometry(100, 100, 300, 300)

        # 分割 上下
        h_splitter = QSplitter(Qt.Vertical)
        h_splitter.addWidget(self.top)
        h_splitter.addWidget(self.buttom)

        # 整体布局
        sbox = QHBoxLayout()

        sbox.addWidget(h_splitter)
        self.setLayout(sbox)

        self.setGeometry(100, 100, 400, 400)
        self.setWindowTitle('Second')
        self.setWindowModality(Qt.ApplicationModal)  # 设置窗口为应用程序模态,阻止和人任何其他窗口进行交互
        self.center()  # 直接调用父类的center方法

    # 发送分析后文件
    def sendText(self):
        self.analyText()
        self.listsignal.emit(l)
        self.close()

    # 分析
    def analyText(self):
        if line_edit.text() == '':
            QMessageBox.information(self, 'information', self.tr('表达式不能为空'))
            return
        if line_key.text() == '':
            QMessageBox.information(self, 'information', self.tr('键不能为空'))
            return
        if line_value.text() == '':
            QMessageBox.information(self, 'information', self.tr('值不能为空'))
            return
        # 规则数组
        str1 = line_edit.text().strip()

        k = line_key.text()  # 替换的键
        v = line_value.text()  # 替换的值
        try:
            global l
            l = list()
            for x in self.label.findChildren(QCheckBox):
                # 找到选中的进行替换
                if x.isChecked():
                    kc = x.text()
                    print(str1.replace(k, kc).replace(v, dic[kc]))
                    newstr = str1.replace(k, kc).replace(v, dic[kc])
                    l.append(newstr)
        except Exception as e:
            print(e)

    # 全选
    def selectAll(self):
        # 遍历所有子控件,然后选中
        for x in self.label.findChildren(QCheckBox):
            x.setChecked(True)

    # 全不选
    def deselectAll(self):
        # 遍历所有子控件,然后取消选中
        for x in self.label.findChildren(QCheckBox):
            x.setChecked(False)

    # 展示下拉框
    def showSelect(self, content):
        ss = str(content).splitlines()  # 分割成行列表

        lable_height = self.geometry().height()  # label的高
        h2 = lable_height - 150 + len(ss) * 21  # 扩大的值

        if lable_height < 250:
            self.label.setMinimumSize(300, 250)
        elif lable_height > 250:
            self.label.setMinimumSize(300, h2)
        elif len(ss) > 100:
            QMessageBox.information(self, 'information', self.tr('暂时支持100条数据'))
            return
        # 创建一个空字典保存数据,全局变量
        global dic
        dic = {}

        for x in ss:
            k = x.strip()
            if k == '':
                continue
            y = ' '.join(k.split())  # 去除两边空格,保留中间一个空格
            vv = y.split(' ')  # 按空格分割
            try:
                dic[vv[0]] = vv[1]
            except Exception as e:
                QMessageBox.information(self, 'information', self.tr('文本格式不正确,请按照:‘AAA BBB’形式传入'))
                # self.close()  # 关闭子窗口
                return  # 停止后面的按钮创建
            cb = QCheckBox(vv[0], self)
            self.vehbox.addWidget(cb)

        self.vehbox.addStretch(0)  # 增加一个伸缩量,都挤到上边,从上往下排列

        self.label.setLayout(self.vehbox)  # 将check放大label中
        self.scroll.setWidget(self.label)

    # 显示子窗口
    def click(self):
        # 因为关闭时删除了,在此重新创建
        self.vehbox = QVBoxLayout()

        if not self.isVisible():
            self.show()

    # 删除控件
    def deleteKong(self):
        # 遍历所有子控件,然后删除
        # 删除QCheckBox
        for x in self.label.findChildren(QCheckBox):
            x.deleteLater()
        # 删除QVBoxLayout
        for y in self.label.findChildren(QVBoxLayout):
            y.deleteLater()

    # 关闭窗口
    def closeEvent(self, event):
        # 清除一些控件
        self.deleteKong()

        # reply = QMessageBox.question(self,
        #                              '本程序',
        #                              "是否要退出程序?",
        #                              QMessageBox.Yes | QMessageBox.No,
        #                              QMessageBox.No)
        # if reply == QMessageBox.Yes:
        #     event.accept()
        # else:
        #     event.ignore()

    # 显示到中间
    def center(self):
        # screen = QDesktopWidget().screenGeometry()
        # size = self.geometry()
        # self.move((screen.width() - size.width()) / 2, (screen.height() - size.height()) / 2)

        qr = self.frameGeometry()
        cp = QDesktopWidget().availableGeometry().center()
        qr.moveCenter(cp)
        self.move(qr.x(), qr.y())


if __name__ == '__main__':
    app = QApplication(sys.argv)
    tool = NeLa2()
    sys.exit(app.exec_())

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值