首页 > 解决方案 > 使用 PyQt5 的 discord bot 控制面板

问题描述

我想用 PyQt5 在 python 中为我的不和谐机器人做一个控制面板。我已经有了我的窗口:

from PyQt5 import QtCore, QtGui, QtWidgets


class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(1023, 457)
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")
       
#some other widgets

        self.pushButton = QtWidgets.QPushButton(self.centralwidget)
        self.pushButton.setGeometry(QtCore.QRect(330, 30, 91, 31))
        font = QtGui.QFont()
        font.setPointSize(16)
        self.pushButton.setFont(font)
        self.pushButton.setObjectName("pushButton")

#some other widgets         

和主要代码:

import discord
import sys
from window import Ui_MainWindow
from PyQt5 import QtCore, QtGui, QtWidgets

prefix = ""
bot = discord.Client

class MyClient(bot):

    async def on_connect(self):
        print("Bot connected to")

    async def on_ready(self):
        print('Logged on as {0}!'.format(self.user))

        for guild in self.guilds:
            if guild.id == 354061299596132392:
                print("guild find")


    async def on_message(self, message):
        print(message.content)

    async def on_diconnect(self):
        print("bot disconnected")



def launcher():
    client = MyClient()
    client.run('TOKEN')



def windowLauncher():



    app = QtWidgets.QApplication(sys.argv)
    MainWindow = QtWidgets.QMainWindow()
    ui = Ui_MainWindow()
    ui.setupUi(MainWindow)
    ui.pushButton.clicked.connect(launcher)
    MainWindow.show()
    sys.exit(app.exec_())


windowLauncher()

但是当我执行这个主代码时,窗口会启动,当我按下按钮启动机器人时,窗口崩溃,但机器人正在运行。我已经尝试使用线程但没有成功。

标签: pythonpyqtpyqt5python-asynciodiscord.py

解决方案


discord 使用 async ,它有自己的事件循环,Qt 处理另一个事件循环,导致一个事件循环阻塞另一个。在这种情况下,解决方案是两者都使用相同的事件循环,并且有几个实现它的库:

  • qasync( python -m pip install qasync)
  • asyncqt( python -m pip install asyncqt)

考虑到上述情况,解决方案是:

import asyncio
import sys

import discord
from qasync import QEventLoop, asyncSlot
# or
# from asyncqt import QEventLoop, asyncSlot

from PyQt5 import QtCore, QtGui, QtWidgets

from window import Ui_MainWindow


prefix = ""


class MyClient(discord.Client):
    async def on_connect(self):
        print("Bot connected to")

    async def on_ready(self):
        print("Logged on as {0}!".format(self.user))

        for guild in self.guilds:
            if guild.id == 354061299596132392:
                print("guild find")

    async def on_message(self, message):
        print(message.content)

    async def on_diconnect(self):
        print("bot disconnected")


class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.setupUi(self)
        self.client = MyClient()
        self.pushButton.clicked.connect(self.on_clicked)

    @asyncSlot()
    async def on_clicked(self):
        await self.client.start("YOUR_TOKEN")


def windowLauncher():

    app = QtWidgets.QApplication(sys.argv)
    loop = QEventLoop(app)
    asyncio.set_event_loop(loop)

    w = MainWindow()
    w.show()
    loop.run_forever()


if __name__ == "__main__":
    windowLauncher()

推荐阅读