使用pyqt5製作簡單計分桌面應用

东血發表於2024-07-11

這是一個自己寫的使用pyqt5製作簡單計分桌面應用的例項,希望對大家有所幫助。製作這個小程式的起因是因為有個藝術類比賽需要設計這個一個桌面程式,方便統分。

(此程式尚存在部分小bug,請慎用,公開程式碼只為讓小白熟悉如何開發一個簡單的桌面計分程式)

ui設計

眾所周知,使用pyqt5開發可以直接使用designer來設計介面,所以,我將頁面程式碼直接貼給大家,具體效果截圖展示。

比賽準備階段介面

image-20240711143434332

比賽進行中介面

image-20240711143507616

完整ui程式碼

為了方便,並沒有轉成.py形式的檔案

<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
 <class>Form</class>
 <widget class="QWidget" name="Form">
  <property name="enabled">
   <bool>true</bool>
  </property>
  <property name="geometry">
   <rect>
    <x>0</x>
    <y>0</y>
    <width>1920</width>
    <height>1080</height>
   </rect>
  </property>
  <property name="minimumSize">
   <size>
    <width>1920</width>
    <height>1080</height>
   </size>
  </property>
  <property name="maximumSize">
   <size>
    <width>1920</width>
    <height>1080</height>
   </size>
  </property>
  <property name="windowTitle">
   <string>Form</string>
  </property>
  <widget class="QWidget" name="race_prepare_page" native="true">
   <property name="enabled">
    <bool>true</bool>
   </property>
   <property name="geometry">
    <rect>
     <x>440</x>
     <y>130</y>
     <width>1211</width>
     <height>721</height>
    </rect>
   </property>
   <property name="styleSheet">
    <string notr="true"/>
   </property>
   <widget class="QTableWidget" name="score_table_display">
    <property name="enabled">
     <bool>true</bool>
    </property>
    <property name="geometry">
     <rect>
      <x>580</x>
      <y>190</y>
      <width>621</width>
      <height>341</height>
     </rect>
    </property>
    <property name="styleSheet">
     <string notr="true">font: 20px ;</string>
    </property>
   </widget>
   <widget class="QLabel" name="score_display_label">
    <property name="geometry">
     <rect>
      <x>830</x>
      <y>540</y>
      <width>131</width>
      <height>41</height>
     </rect>
    </property>
    <property name="styleSheet">
     <string notr="true">font: 20px &quot;Adobe Arabic&quot;;</string>
    </property>
    <property name="text">
     <string>選手資訊展示</string>
    </property>
   </widget>
   <widget class="QPushButton" name="race_info_button">
    <property name="geometry">
     <rect>
      <x>200</x>
      <y>660</y>
      <width>121</width>
      <height>51</height>
     </rect>
    </property>
    <property name="styleSheet">
     <string notr="true">font: 20px &quot;Adobe Arabic&quot;;</string>
    </property>
    <property name="text">
     <string>確認資訊</string>
    </property>
   </widget>
   <widget class="QPushButton" name="race_start_button">
    <property name="geometry">
     <rect>
      <x>740</x>
      <y>90</y>
      <width>121</width>
      <height>51</height>
     </rect>
    </property>
    <property name="styleSheet">
     <string notr="true">font: 20px &quot;Adobe Arabic&quot;;</string>
    </property>
    <property name="text">
     <string>比賽開始</string>
    </property>
   </widget>
   <widget class="QLabel" name="race_preparation_label">
    <property name="geometry">
     <rect>
      <x>510</x>
      <y>10</y>
      <width>181</width>
      <height>41</height>
     </rect>
    </property>
    <property name="styleSheet">
     <string notr="true">font: 30px &quot;Adobe Arabic&quot;;</string>
    </property>
    <property name="text">
     <string>比賽準備階段</string>
    </property>
   </widget>
   <widget class="QLabel" name="music_name_label">
    <property name="enabled">
     <bool>true</bool>
    </property>
    <property name="geometry">
     <rect>
      <x>10</x>
      <y>350</y>
      <width>91</width>
      <height>81</height>
     </rect>
    </property>
    <property name="styleSheet">
     <string notr="true">font: 20px &quot;Adobe Arabic&quot;;</string>
    </property>
    <property name="text">
     <string>請按選手排序輸入曲名名稱</string>
    </property>
    <property name="wordWrap">
     <bool>true</bool>
    </property>
   </widget>
   <widget class="QRadioButton" name="remove_yes">
    <property name="geometry">
     <rect>
      <x>250</x>
      <y>560</y>
      <width>61</width>
      <height>21</height>
     </rect>
    </property>
    <property name="styleSheet">
     <string notr="true">font: 20px &quot;Adobe Arabic&quot;;</string>
    </property>
    <property name="text">
     <string>是</string>
    </property>
   </widget>
   <widget class="QLineEdit" name="judge_number_input">
    <property name="geometry">
     <rect>
      <x>100</x>
      <y>110</y>
      <width>151</width>
      <height>31</height>
     </rect>
    </property>
    <property name="styleSheet">
     <string notr="true">font: 20px ;</string>
    </property>
    <property name="text">
     <string/>
    </property>
    <property name="placeholderText">
     <string>填寫示例:1</string>
    </property>
   </widget>
   <widget class="QLabel" name="race_name_label">
    <property name="geometry">
     <rect>
      <x>10</x>
      <y>60</y>
      <width>91</width>
      <height>24</height>
     </rect>
    </property>
    <property name="styleSheet">
     <string notr="true">font: 20px &quot;Adobe Arabic&quot;;</string>
    </property>
    <property name="text">
     <string>比賽名稱</string>
    </property>
   </widget>
   <widget class="QTextEdit" name="judge_namelist_input">
    <property name="geometry">
     <rect>
      <x>100</x>
      <y>160</y>
      <width>151</width>
      <height>171</height>
     </rect>
    </property>
    <property name="styleSheet">
     <string notr="true">font: 20px;</string>
    </property>
    <property name="markdown">
     <string/>
    </property>
    <property name="html">
     <string>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
p, li { white-space: pre-wrap; }
&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'SimSun'; font-size:20px; font-weight:400; font-style:normal;&quot;&gt;
&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
    </property>
    <property name="placeholderText">
     <string>填寫示例:   張三                 李四</string>
    </property>
   </widget>
   <widget class="QLabel" name="judge_number_label">
    <property name="geometry">
     <rect>
      <x>11</x>
      <y>116</y>
      <width>81</width>
      <height>24</height>
     </rect>
    </property>
    <property name="styleSheet">
     <string notr="true">font: 20px &quot;Adobe Arabic&quot;;</string>
    </property>
    <property name="text">
     <string>評委數量</string>
    </property>
   </widget>
   <widget class="QTextEdit" name="player_namelist_input">
    <property name="geometry">
     <rect>
      <x>390</x>
      <y>160</y>
      <width>151</width>
      <height>171</height>
     </rect>
    </property>
    <property name="styleSheet">
     <string notr="true">font: 20px;</string>
    </property>
    <property name="markdown">
     <string/>
    </property>
    <property name="html">
     <string>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
p, li { white-space: pre-wrap; }
&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'SimSun'; font-size:20px; font-weight:400; font-style:normal;&quot;&gt;
&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
    </property>
    <property name="placeholderText">
     <string>填寫示例:   張三               李四</string>
    </property>
   </widget>
   <widget class="QLabel" name="player_name_label">
    <property name="geometry">
     <rect>
      <x>300</x>
      <y>160</y>
      <width>91</width>
      <height>81</height>
     </rect>
    </property>
    <property name="styleSheet">
     <string notr="true">font: 20px &quot;Adobe Arabic&quot;;</string>
    </property>
    <property name="text">
     <string>請按選手排序輸入姓名</string>
    </property>
    <property name="wordWrap">
     <bool>true</bool>
    </property>
   </widget>
   <widget class="QLineEdit" name="race_name_input">
    <property name="geometry">
     <rect>
      <x>100</x>
      <y>54</y>
      <width>441</width>
      <height>31</height>
     </rect>
    </property>
    <property name="accessibleName">
     <string/>
    </property>
    <property name="styleSheet">
     <string notr="true">font: 20px;</string>
    </property>
    <property name="inputMask">
     <string/>
    </property>
    <property name="text">
     <string/>
    </property>
    <property name="placeholderText">
     <string>預設比賽</string>
    </property>
   </widget>
   <widget class="QLabel" name="judge_name_label">
    <property name="geometry">
     <rect>
      <x>10</x>
      <y>160</y>
      <width>91</width>
      <height>81</height>
     </rect>
    </property>
    <property name="styleSheet">
     <string notr="true">font: 20px &quot;Adobe Arabic&quot;;</string>
    </property>
    <property name="text">
     <string>請按評委排序輸入姓名</string>
    </property>
    <property name="wordWrap">
     <bool>true</bool>
    </property>
   </widget>
   <widget class="QLineEdit" name="player_number_input">
    <property name="geometry">
     <rect>
      <x>390</x>
      <y>110</y>
      <width>151</width>
      <height>31</height>
     </rect>
    </property>
    <property name="styleSheet">
     <string notr="true">font: 20px ;</string>
    </property>
    <property name="text">
     <string/>
    </property>
    <property name="placeholderText">
     <string>填寫示例:1</string>
    </property>
   </widget>
   <widget class="QRadioButton" name="remove_no">
    <property name="geometry">
     <rect>
      <x>340</x>
      <y>560</y>
      <width>51</width>
      <height>21</height>
     </rect>
    </property>
    <property name="styleSheet">
     <string notr="true">font: 20px &quot;Adobe Arabic&quot;;</string>
    </property>
    <property name="text">
     <string>否</string>
    </property>
   </widget>
   <widget class="QLabel" name="remove_score_label">
    <property name="geometry">
     <rect>
      <x>10</x>
      <y>614</y>
      <width>221</width>
      <height>24</height>
     </rect>
    </property>
    <property name="styleSheet">
     <string notr="true">font: 20px &quot;Adobe Arabic&quot;;</string>
    </property>
    <property name="text">
     <string>去掉幾個最高分和最低分</string>
    </property>
   </widget>
   <widget class="QLineEdit" name="remove_score_input">
    <property name="geometry">
     <rect>
      <x>250</x>
      <y>610</y>
      <width>151</width>
      <height>31</height>
     </rect>
    </property>
    <property name="styleSheet">
     <string notr="true">font: 20px ;</string>
    </property>
    <property name="text">
     <string/>
    </property>
    <property name="placeholderText">
     <string>填寫示例:1</string>
    </property>
   </widget>
   <widget class="QLabel" name="player_number_label">
    <property name="geometry">
     <rect>
      <x>300</x>
      <y>116</y>
      <width>91</width>
      <height>24</height>
     </rect>
    </property>
    <property name="styleSheet">
     <string notr="true">font: 20px &quot;Adobe Arabic&quot;;</string>
    </property>
    <property name="text">
     <string>選手數量</string>
    </property>
   </widget>
   <widget class="QLabel" name="remove_choose_label">
    <property name="geometry">
     <rect>
      <x>10</x>
      <y>560</y>
      <width>221</width>
      <height>24</height>
     </rect>
    </property>
    <property name="styleSheet">
     <string notr="true">font: 20px &quot;Adobe Arabic&quot;;</string>
    </property>
    <property name="text">
     <string>是否去掉最高分和最低分</string>
    </property>
   </widget>
   <widget class="QTextEdit" name="music_namelist_input">
    <property name="geometry">
     <rect>
      <x>100</x>
      <y>350</y>
      <width>441</width>
      <height>181</height>
     </rect>
    </property>
    <property name="styleSheet">
     <string notr="true">font: 20px;</string>
    </property>
    <property name="markdown">
     <string/>
    </property>
    <property name="html">
     <string>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
p, li { white-space: pre-wrap; }
&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'SimSun'; font-size:20px; font-weight:400; font-style:normal;&quot;&gt;
&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
    </property>
    <property name="placeholderText">
     <string>填寫示例:                                  古典樂                                       爵士樂</string>
    </property>
   </widget>
   <widget class="QPushButton" name="continue_race_button">
    <property name="geometry">
     <rect>
      <x>890</x>
      <y>90</y>
      <width>151</width>
      <height>51</height>
     </rect>
    </property>
    <property name="styleSheet">
     <string notr="true">font: 20px &quot;Adobe Arabic&quot;;</string>
    </property>
    <property name="text">
     <string>繼續上次比賽</string>
    </property>
   </widget>
   <widget class="QPushButton" name="quit_code_button">
    <property name="geometry">
     <rect>
      <x>1070</x>
      <y>90</y>
      <width>121</width>
      <height>51</height>
     </rect>
    </property>
    <property name="styleSheet">
     <string notr="true">font: 20px &quot;Adobe Arabic&quot;;</string>
    </property>
    <property name="text">
     <string>退出程式</string>
    </property>
   </widget>
   <widget class="QPushButton" name="save_info_button">
    <property name="geometry">
     <rect>
      <x>590</x>
      <y>90</y>
      <width>121</width>
      <height>51</height>
     </rect>
    </property>
    <property name="styleSheet">
     <string notr="true">font: 20px &quot;Adobe Arabic&quot;;</string>
    </property>
    <property name="text">
     <string>儲存資訊</string>
    </property>
   </widget>
  </widget>
  <widget class="QWidget" name="race_going_page" native="true">
   <property name="geometry">
    <rect>
     <x>440</x>
     <y>130</y>
     <width>1211</width>
     <height>721</height>
    </rect>
   </property>
   <widget class="QLabel" name="race_going_label">
    <property name="geometry">
     <rect>
      <x>0</x>
      <y>10</y>
      <width>1211</width>
      <height>41</height>
     </rect>
    </property>
    <property name="styleSheet">
     <string notr="true">font: 30px &quot;Adobe Arabic&quot;;</string>
    </property>
    <property name="text">
     <string>比賽進行階段</string>
    </property>
    <property name="alignment">
     <set>Qt::AlignCenter</set>
    </property>
   </widget>
   <widget class="QLabel" name="judge_one_label_1">
    <property name="geometry">
     <rect>
      <x>80</x>
      <y>146</y>
      <width>181</width>
      <height>41</height>
     </rect>
    </property>
    <property name="styleSheet">
     <string notr="true">font: 20px;</string>
    </property>
    <property name="text">
     <string>姓名:1號評委</string>
    </property>
   </widget>
   <widget class="QLineEdit" name="judgeone_score_input_1">
    <property name="geometry">
     <rect>
      <x>300</x>
      <y>150</y>
      <width>151</width>
      <height>31</height>
     </rect>
    </property>
    <property name="styleSheet">
     <string notr="true">font: 20px ;</string>
    </property>
    <property name="text">
     <string/>
    </property>
    <property name="placeholderText">
     <string>填寫示例:1</string>
    </property>
   </widget>
   <widget class="QLabel" name="judge_one_label_2">
    <property name="geometry">
     <rect>
      <x>81</x>
      <y>202</y>
      <width>181</width>
      <height>41</height>
     </rect>
    </property>
    <property name="styleSheet">
     <string notr="true">font: 20px;</string>
    </property>
    <property name="text">
     <string>姓名:2號評委</string>
    </property>
   </widget>
   <widget class="QLineEdit" name="judgeone_score_input_2">
    <property name="geometry">
     <rect>
      <x>301</x>
      <y>206</y>
      <width>151</width>
      <height>31</height>
     </rect>
    </property>
    <property name="styleSheet">
     <string notr="true">font: 20px ;</string>
    </property>
    <property name="text">
     <string/>
    </property>
    <property name="placeholderText">
     <string>填寫示例:1</string>
    </property>
   </widget>
   <widget class="QLabel" name="judge_one_label_3">
    <property name="geometry">
     <rect>
      <x>81</x>
      <y>252</y>
      <width>181</width>
      <height>41</height>
     </rect>
    </property>
    <property name="styleSheet">
     <string notr="true">font: 20px;</string>
    </property>
    <property name="text">
     <string>姓名:3號評委</string>
    </property>
   </widget>
   <widget class="QLineEdit" name="judgeone_score_input_3">
    <property name="geometry">
     <rect>
      <x>301</x>
      <y>256</y>
      <width>151</width>
      <height>31</height>
     </rect>
    </property>
    <property name="styleSheet">
     <string notr="true">font: 20px ;</string>
    </property>
    <property name="text">
     <string/>
    </property>
    <property name="placeholderText">
     <string>填寫示例:1</string>
    </property>
   </widget>
   <widget class="QLineEdit" name="judgeone_score_input_4">
    <property name="geometry">
     <rect>
      <x>300</x>
      <y>310</y>
      <width>151</width>
      <height>31</height>
     </rect>
    </property>
    <property name="styleSheet">
     <string notr="true">font: 20px ;</string>
    </property>
    <property name="text">
     <string/>
    </property>
    <property name="placeholderText">
     <string>填寫示例:1</string>
    </property>
   </widget>
   <widget class="QLabel" name="judge_one_label_4">
    <property name="geometry">
     <rect>
      <x>80</x>
      <y>306</y>
      <width>181</width>
      <height>41</height>
     </rect>
    </property>
    <property name="styleSheet">
     <string notr="true">font: 20px;</string>
    </property>
    <property name="text">
     <string>姓名:4號評委</string>
    </property>
   </widget>
   <widget class="QLabel" name="judge_one_label_5">
    <property name="geometry">
     <rect>
      <x>81</x>
      <y>362</y>
      <width>181</width>
      <height>41</height>
     </rect>
    </property>
    <property name="styleSheet">
     <string notr="true">font: 20px;</string>
    </property>
    <property name="text">
     <string>姓名:5號評委</string>
    </property>
   </widget>
   <widget class="QLineEdit" name="judgeone_score_input_5">
    <property name="geometry">
     <rect>
      <x>301</x>
      <y>366</y>
      <width>151</width>
      <height>31</height>
     </rect>
    </property>
    <property name="styleSheet">
     <string notr="true">font: 20px ;</string>
    </property>
    <property name="text">
     <string/>
    </property>
    <property name="placeholderText">
     <string>填寫示例:1</string>
    </property>
   </widget>
   <widget class="QLabel" name="judge_one_label_6">
    <property name="geometry">
     <rect>
      <x>81</x>
      <y>422</y>
      <width>181</width>
      <height>41</height>
     </rect>
    </property>
    <property name="styleSheet">
     <string notr="true">font: 20px;</string>
    </property>
    <property name="text">
     <string>姓名:6號評委</string>
    </property>
   </widget>
   <widget class="QLineEdit" name="judgeone_score_input_6">
    <property name="geometry">
     <rect>
      <x>301</x>
      <y>426</y>
      <width>151</width>
      <height>31</height>
     </rect>
    </property>
    <property name="styleSheet">
     <string notr="true">font: 20px ;</string>
    </property>
    <property name="text">
     <string/>
    </property>
    <property name="placeholderText">
     <string>填寫示例:1</string>
    </property>
   </widget>
   <widget class="QLabel" name="judge_one_label_7">
    <property name="geometry">
     <rect>
      <x>81</x>
      <y>482</y>
      <width>181</width>
      <height>41</height>
     </rect>
    </property>
    <property name="styleSheet">
     <string notr="true">font: 20px;</string>
    </property>
    <property name="text">
     <string>姓名:7號評委</string>
    </property>
   </widget>
   <widget class="QLineEdit" name="judgeone_score_input_7">
    <property name="geometry">
     <rect>
      <x>301</x>
      <y>486</y>
      <width>151</width>
      <height>31</height>
     </rect>
    </property>
    <property name="styleSheet">
     <string notr="true">font: 20px ;</string>
    </property>
    <property name="text">
     <string/>
    </property>
    <property name="placeholderText">
     <string>填寫示例:1</string>
    </property>
   </widget>
   <widget class="QLabel" name="judge_one_label_8">
    <property name="geometry">
     <rect>
      <x>81</x>
      <y>542</y>
      <width>181</width>
      <height>41</height>
     </rect>
    </property>
    <property name="styleSheet">
     <string notr="true">font: 20px;</string>
    </property>
    <property name="text">
     <string>姓名:8號評委</string>
    </property>
   </widget>
   <widget class="QLineEdit" name="judgeone_score_input_8">
    <property name="geometry">
     <rect>
      <x>301</x>
      <y>546</y>
      <width>151</width>
      <height>31</height>
     </rect>
    </property>
    <property name="styleSheet">
     <string notr="true">font: 20px ;</string>
    </property>
    <property name="text">
     <string/>
    </property>
    <property name="placeholderText">
     <string>填寫示例:1</string>
    </property>
   </widget>
   <widget class="QLabel" name="judge_one_label_9">
    <property name="geometry">
     <rect>
      <x>81</x>
      <y>602</y>
      <width>181</width>
      <height>41</height>
     </rect>
    </property>
    <property name="styleSheet">
     <string notr="true">font: 20px;</string>
    </property>
    <property name="text">
     <string>姓名:9號評委</string>
    </property>
   </widget>
   <widget class="QLineEdit" name="judgeone_score_input_9">
    <property name="geometry">
     <rect>
      <x>301</x>
      <y>606</y>
      <width>151</width>
      <height>31</height>
     </rect>
    </property>
    <property name="styleSheet">
     <string notr="true">font: 20px ;</string>
    </property>
    <property name="text">
     <string/>
    </property>
    <property name="placeholderText">
     <string>填寫示例:1</string>
    </property>
   </widget>
   <widget class="QLabel" name="judge_com_label_1">
    <property name="geometry">
     <rect>
      <x>510</x>
      <y>250</y>
      <width>151</width>
      <height>41</height>
     </rect>
    </property>
    <property name="styleSheet">
     <string notr="true">font: 24px;</string>
    </property>
    <property name="text">
     <string>最高分:</string>
    </property>
   </widget>
   <widget class="QLabel" name="judge_com_label_2">
    <property name="geometry">
     <rect>
      <x>700</x>
      <y>250</y>
      <width>161</width>
      <height>41</height>
     </rect>
    </property>
    <property name="styleSheet">
     <string notr="true">font: 24px;</string>
    </property>
    <property name="text">
     <string>最低分:</string>
    </property>
   </widget>
   <widget class="QLabel" name="judge_com_label_3">
    <property name="geometry">
     <rect>
      <x>510</x>
      <y>320</y>
      <width>151</width>
      <height>41</height>
     </rect>
    </property>
    <property name="styleSheet">
     <string notr="true">font: 30px;</string>
    </property>
    <property name="text">
     <string>實際得分:</string>
    </property>
   </widget>
   <widget class="QLabel" name="judge_com_label_4">
    <property name="geometry">
     <rect>
      <x>670</x>
      <y>300</y>
      <width>181</width>
      <height>81</height>
     </rect>
    </property>
    <property name="styleSheet">
     <string notr="true">font: 60px;</string>
    </property>
    <property name="text">
     <string/>
    </property>
   </widget>
   <widget class="QPushButton" name="next_player_button">
    <property name="geometry">
     <rect>
      <x>630</x>
      <y>170</y>
      <width>151</width>
      <height>51</height>
     </rect>
    </property>
    <property name="styleSheet">
     <string notr="true">font: 20px &quot;Adobe Arabic&quot;;</string>
    </property>
    <property name="text">
     <string>下一個選手</string>
    </property>
   </widget>
   <widget class="QPushButton" name="exit_race_button">
    <property name="geometry">
     <rect>
      <x>970</x>
      <y>170</y>
      <width>151</width>
      <height>51</height>
     </rect>
    </property>
    <property name="styleSheet">
     <string notr="true">font: 20px &quot;Adobe Arabic&quot;;</string>
    </property>
    <property name="text">
     <string>比賽結束</string>
    </property>
   </widget>
   <widget class="QLabel" name="current_player_label">
    <property name="geometry">
     <rect>
      <x>80</x>
      <y>90</y>
      <width>1091</width>
      <height>41</height>
     </rect>
    </property>
    <property name="styleSheet">
     <string notr="true">font: 24px;</string>
    </property>
    <property name="text">
     <string>當前選手:</string>
    </property>
   </widget>
   <widget class="QPushButton" name="player_quit_button">
    <property name="geometry">
     <rect>
      <x>800</x>
      <y>170</y>
      <width>151</width>
      <height>51</height>
     </rect>
    </property>
    <property name="styleSheet">
     <string notr="true">font: 20px &quot;Adobe Arabic&quot;;</string>
    </property>
    <property name="text">
     <string>當前選手棄權</string>
    </property>
   </widget>
  </widget>
 </widget>
 <resources/>
 <connections/>
</ui>

程式碼設計

程式主要功能包含,檔案上傳,檔案讀取,分數計算,然後還有一些按鈕繫結事件。

from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
from PyQt5 import uic

import keyboard
import sys
import os
import pandas as pd
import docx

def get_path(relative_path):
    try:
        base_path = sys._MEIPASS
    except AttributeError:
        base_path = os.path.abspath(".")

    return os.path.normpath(os.path.join(base_path, relative_path))

def get_decimal_places(num):
    import decimal
    if '.' in str(num):
        num = str(float(num))   #如果傳入的是字串形式的浮點數,先去掉小數後面無意義的0
    d = decimal.Decimal(str(num))
    return abs(d.as_tuple().exponent)

def del_files(path_file):
    ls = os.listdir(path_file)
    for i in ls:
        f_path = os.path.join(path_file, i)
        # 判斷是否是一個目錄,若是,則遞迴刪除
        if os.path.isdir(f_path):
            del_files(f_path)
        else:
            os.remove(f_path)


class MyWindow(QWidget):
    def __init__(self):
        super().__init__()
        self.ui = uic.loadUi(get_path("assets/comscore_final.ui")) #讀取ui檔案
        # 展示視窗
        self.ui.setWindowTitle('比賽計分系統')

        self.ui.setWindowFlag(Qt.WindowCloseButtonHint, False)
        
        #提取每個要使用的控制元件 
        #比賽準備階段  
        self.race_prepare=self.ui.race_prepare_page #比賽準備頁面

        self.race_name=self.ui.race_name_input #比賽名稱

        self.judge_number=self.ui.judge_number_input #評委數量
        self.judge_namelist=self.ui.judge_namelist_input #評委資訊

        self.player_number=self.ui.player_number_input #選手數量
        self.player_namelist=self.ui.player_namelist_input #選手資訊

        self.music_namelist=self.ui.music_namelist_input #音樂資訊

        self.race_info=self.ui.race_info_button #確認資訊按鈕

        self.continue_race=self.ui.continue_race_button #繼續上次比賽按鈕
        self.race_start=self.ui.race_start_button #比賽開始按鈕'
        self.remove_score=self.ui.remove_score_input 
        self.save_info=self.ui.save_info_button #儲存資訊
        self.quit_code=self.ui.quit_code_button #退出程式

        self.race_start.setEnabled(False)
        self.save_info.setEnabled(False)

        #是否去掉最高分和最低分
        self.remove_yes_radiobox=self.ui.remove_yes
        self.remove_no_radiobox=self.ui.remove_no

        #去掉最高分和最低分的數量
        self.remove_score_label_now=self.ui.remove_score_label
        self.remove_score=self.ui.remove_score_input 

        #預設選擇不去掉,並且設定不顯示去掉幾個最高分和最低分的框
        self.remove_no_radiobox.setChecked(True)
        self.remove_score.setVisible(False) #初始設定隱藏
        self.remove_score_label_now.setVisible(False) #初始設定隱藏

        #toggled訊號與槽函式繫結
        self.remove_yes_radiobox.toggled.connect(lambda :self.func_radiobox_btnstate(self.remove_yes_radiobox))
        self.remove_no_radiobox.toggled.connect(lambda :self.func_radiobox_btnstate(self.remove_no_radiobox))

        #選手資訊展示
        self.score_table=self.ui.score_table_display #選手資訊展示

        # 繫結訊號與槽函式
        self.race_info.clicked.connect(self.func_race_info) #資訊匯入
        self.continue_race.clicked.connect(self.func_continue_race)# 根據檔案來讀取資訊
        self.race_start.clicked.connect(self.func_race_start) #比賽開始按鈕
        self.save_info.clicked.connect(self.func_save_info) #儲存資訊
        self.quit_code.clicked.connect(self.func_quit_code)


        #選手資訊展示區域函式
        self.score_table.setSelectionMode(QAbstractItemView.SingleSelection)#設定選取方式為單個選取
        self.score_table.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOn) #設定水平滾動
        self.score_table.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn)  #設定豎直滾動

        #---------------------------------------------------------------------------------------------------------------------
        #---------------------------------------------------------------------------------------------------------------------

        #比賽進行階段
        self.race_going=self.ui.race_going_page #比賽進行頁面
        self.race_going.setVisible(False) #初始設定隱藏

        self.race_going_name=self.ui.race_going_label

        #當前選手
        self.current_player=self.ui.current_player_label 

        #評委列表
        self.judge_one_1=self.ui.judge_one_label_1
        self.judgeone_score_1=self.ui.judgeone_score_input_1

        #設定校驗規則,例項化浮點校驗器,並設定範圍0~10,精度為小數點兩位
        myValidator = QRegExpValidator(QRegExp("^(10|\d(\.\d{1,2})?)$"))

        #初始設定隱藏
        for show_i in range(1,10):
            judge_one_label_name="judge_one_label_"+str(show_i)
            judge_one_temp = self.race_going.findChild(QLabel,judge_one_label_name)
            judge_one_temp.setVisible(False)

            judgeone_score_input_name="judgeone_score_input_"+str(show_i)
            judgeone_score_temp = self.race_going.findChild(QLineEdit,judgeone_score_input_name)
            judgeone_score_temp.setVisible(False)
            #設定校驗規則,限制只能輸入數字還有小數後兩位
            judgeone_score_temp.returnPressed.connect(self.func_text_change)
            judgeone_score_temp.setValidator(myValidator)
        
        #最高分,最低分,實際得分
        self.judge_com_max=self.ui.judge_com_label_1  #最高分
        self.judge_com_min=self.ui.judge_com_label_2  #最低分
        self.judge_com_average_label=self.ui.judge_com_label_3  #實際得分標籤
        self.judge_com_average=self.ui.judge_com_label_4 #分數
        for show_i in range(1,5):
            judge_com_label_name="judge_com_label_"+str(show_i)
            judge_com_temp = self.race_going.findChild(QLabel,judge_com_label_name)
            judge_com_temp.setVisible(False)

        #計算總分按鈕
        # self.com_score=self.ui.com_score_button 

        #下一個選手按鈕
        self.next_player=self.ui.next_player_button 

        #比賽結束按鈕
        self.exit_race=self.ui.exit_race_button 

        #選手棄權按鈕
        self.player_quit=self.ui.player_quit_button


        # 繫結訊號與槽函式
        # self.com_score.clicked.connect(self.func_com_score) #計算總分
        self.next_player.clicked.connect(self.func_next_player) #下一個選手
        self.exit_race.clicked.connect(self.func_exit_race) #結束比賽
        self.player_quit.clicked.connect(self.func_player_quit) #選手棄權
        
        #賦予一個全域性使用的資料變數
        self.all_data_df=[]
        self.have_score_number=0 #表示當前已經計分的選手數量
        self.remove_score_number=0

    def func_save_info(self):
        reply_one=self.setQMessageBoxtwoButtonTextENToCN('提示', '是否儲存資訊?',QMessageBox.Question)
        if reply_one == QMessageBox.Yes: 
            #先將讀取的資料儲存起來,以tablewight資料表資訊為準
            player_index=[]
            player_name=[]
            music_name=[]
            for qtable_row in range(int(self.player_number.text())):
                player_index.append(self.score_table.item(qtable_row,0).text())  #獲取某行某列item中的x資訊
                player_name.append(self.score_table.item(qtable_row,1).text())  #獲取某行某列item中的x資訊
                music_name.append(self.score_table.item(qtable_row,2).text())  #獲取某行某列item中的x資訊
            
            judge_all_list=[]
            for qtable_column in range(int(self.judge_number.text())):
                judge_one_list=[' ']*int(self.player_number.text()) #將列資料全部填充為空格
                judge_all_list.append(judge_one_list)

            # creating the DataFrame
            all_data = pd.DataFrame(list(zip(player_index, player_name, music_name))) 

            all_data.columns =['抽籤序號', '選手姓名', '曲目名稱'] #設定列名

            judge_namelist_temp=self.judge_namelist.toPlainText().split('\n')
            for qtable_column in range(int(self.judge_number.text())):
                judge_one_list=[' ']*int(self.player_number.text()) #將列資料全部填充為空格
                judge_column_name=judge_namelist_temp[qtable_column]+":"+str(qtable_column+1)+"號評委"
                all_data[judge_column_name]=judge_one_list

            #增加最高分,最低分列 ,增加實際得分列
            if self.remove_yes_radiobox.isChecked()==True:
                max_one_list=[' ']*int(self.player_number.text()) #將列資料全部填充為空格
                all_data['最高分']=max_one_list

                min_one_list=[' ']*int(self.player_number.text()) #將列資料全部填充為空格
                all_data['最低分']=min_one_list

                visual_one_list=[-1]*int(self.player_number.text()) #將列資料全部填充為空格
                all_data['實得分']=visual_one_list

                index_one_list=[' ']*int(self.player_number.text()) #將列資料全部填充為空格
                all_data['最終排名']=index_one_list

                remove_score_str=self.remove_score.text()
                self.remove_score_number=int(self.remove_score.text())
                remove_one_list=[remove_score_str]*int(self.player_number.text()) #將列資料全部填充為空格
                all_data['去掉幾個最高分']=remove_one_list
            else:
                visual_one_list=[-1]*int(self.player_number.text()) #將列資料全部填充為空格
                all_data['實得分']=visual_one_list

                index_one_list=[' ']*int(self.player_number.text()) #將列資料全部填充為空格
                all_data['最終排名']=index_one_list

                remove_one_list=['0']*int(self.player_number.text()) #將列資料全部填充為空格
                all_data['去掉幾個最高分']=remove_one_list

            all_data['抽籤序號']=all_data['抽籤序號'].astype(int)
            all_data=all_data.sort_values(by=['抽籤序號']) #按照抽籤序號排序
            all_data=all_data.reset_index(drop=True) #重新排列一下索引

            all_data.to_excel('temp_data/'+str(self.race_name.text())+'_臨時儲存資料.xlsx', sheet_name='部分資訊', index=True) # index false為不寫入索引
            
            #恢復所有資料初始狀態
            self.all_data_df=[]
            self.have_score_number=0 #表示當前已經計分的選手數量
            self.remove_score_number=0

            #預設選擇不去掉,並且設定不顯示去掉幾個最高分和最低分的框
            self.remove_no_radiobox.setChecked(True)
            self.remove_score.setVisible(False) #初始設定隱藏
            self.remove_score_label_now.setVisible(False) #初始設定隱藏

            #然後要清空所有的輸入
            self.race_name.setText("") #比賽名稱

            self.judge_number.setText("") #評委數量
            self.judge_namelist.setText("") #評委資訊

            self.player_number.setText("") #選手數量
            self.player_namelist.setText("") #選手資訊

            self.music_namelist.setText("") #音樂資訊

            #然後清空qtablewight
            self.score_table.setRowCount(0)
            self.score_table.setColumnCount(0)
            self.score_table.clearContents()

            #設定按鈕不可用
            self.race_start.setEnabled(False)
            self.save_info.setEnabled(False)

            self.setQMessageBoxoneButtonTextENToCN("提示","儲存資訊成功",QMessageBox.Information)
            return
        else:
            self.setQMessageBoxoneButtonTextENToCN("提示","使用者取消操作",QMessageBox.Information)
            return
        return

        return


    def func_quit_code(self):
        reply_one=self.setQMessageBoxtwoButtonTextENToCN('提示', '是否退出程式?',QMessageBox.Question)
        if reply_one == QMessageBox.Yes: 
            self.setQMessageBoxoneButtonTextENToCN("提示","退出程式成功",QMessageBox.Information)
            sys.exit(0)
            return
        else:
            self.setQMessageBoxoneButtonTextENToCN("提示","使用者取消操作",QMessageBox.Information)
            return
        return

    def func_text_change(self):
        #在輸入框內按下enter,就會進入這裡
        #獲取資料,儲存這個選手的得分到臨時表格中
        all_data_temp=self.all_data_df

        judge_number=0
        if int(all_data_temp.loc[0,'去掉幾個最高分'])>0:
            judge_number=int(all_data_temp.shape[1])-8
        else:
            judge_number=int(all_data_temp.shape[1])-6

        #遍歷所有輸入框,然後找到第一個為空的輸入框,設定它為setFocus即可
        for com_i in range(1,judge_number+1):
            judgeone_score_input_name="judgeone_score_input_"+str(com_i)
            judgeone_score_temp = self.race_going.findChild(QLineEdit,judgeone_score_input_name)
            if judgeone_score_temp.text()=='':
                judgeone_score_temp.setFocus()
                return
            else:
                continue

        #獲取資料,儲存這個選手的得分到臨時表格中
        all_data_temp=self.all_data_df
        print(self.all_data_df)
        reply_zero=self.setQMessageBoxtwoButtonTextENToCN('提示', '評委得分是否輸入正確?',QMessageBox.Question)
        if reply_zero == QMessageBox.Yes:
            #根據評委數量來獲取輸入框資料
            score_list_temp=[]
            save_score_list=[]
            judge_number=0
            if int(all_data_temp.loc[0,'去掉幾個最高分'])>0:
                judge_number=int(all_data_temp.shape[1])-8
            else:
                judge_number=int(all_data_temp.shape[1])-6

            print(judge_number)
            for com_i in range(1,judge_number+1):
                judgeone_score_input_name="judgeone_score_input_"+str(com_i)
                judgeone_score_temp = self.race_going.findChild(QLineEdit,judgeone_score_input_name)

                judgeone_score_temp.setReadOnly(True)  #設定為只讀
                
                if judgeone_score_temp.text()=='':
                    self.setQMessageBoxoneButtonTextENToCN("提示",str(com_i)+"評委分數未填寫",QMessageBox.Information)
                    return
                else:
                    score_list_temp.append(float(judgeone_score_temp.text()))
                    save_score_list.append(float(judgeone_score_temp.text()))
            
            print(score_list_temp)
            score_list_temp.sort() #對打分進行排序
            
            #設定最高分
            score_list_temp_max=max(score_list_temp)
            self.judge_com_max.setText("最高分: "+str(score_list_temp_max))
            # self.score_table.setText(score_list_temp_max)

            #設定最低分
            score_list_temp_min=min(score_list_temp)
            self.judge_com_min.setText("最低分: "+str(score_list_temp_min))

            for flag in range(self.remove_score_number):
                score_list_temp.pop() #刪除最後一項
                score_list_temp.pop(0) #刪除第一項

            #設定最終分數
            average_score=round(sum(score_list_temp)/len(score_list_temp),3)
            #設定
            self.judge_com_average.setText(str(average_score))

            #確定當前計算的是哪個選手,至少有一個評委
            current_player_row=0
            player_row=int(all_data_temp.shape[0])
            for player_row_index in range(0,player_row):
                print(str(all_data_temp.iloc[player_row_index,int(all_data_temp.shape[1])-3]))
                print(str(all_data_temp.iloc[player_row_index,int(all_data_temp.shape[1])-3])=='-1')
                if str(all_data_temp.iloc[player_row_index,int(all_data_temp.shape[1])-3])=='-1' or str(all_data_temp.iloc[player_row_index,int(all_data_temp.shape[1])-3])=='-1.0':
                    current_player_row=player_row_index
                    break
                current_player_row=player_row_index
            
            self.have_score_number=current_player_row
            #儲存方法在有最高分和沒有最高分時有所不同,有
            if int(all_data_temp.loc[0,'去掉幾個最高分'])>0:
            #將這裡面的資料進行覆蓋  操作的是save_score_list,score_list_temp_max,score_list_temp_min
                print(save_score_list)
                for judge_number_index in range(0,judge_number):
                    print(judge_number_index)
                    all_data_temp.iloc[current_player_row,judge_number_index+3]=save_score_list[judge_number_index]   
                
                all_data_temp.iloc[current_player_row,judge_number_index+4]=score_list_temp_max 
                all_data_temp.iloc[current_player_row,judge_number_index+5]=score_list_temp_min
                all_data_temp.iloc[current_player_row,judge_number_index+6]=average_score
            else:
                for judge_number_index in range(0,judge_number):
                    all_data_temp.iloc[current_player_row,judge_number_index+3]=save_score_list[judge_number_index]   
                
                all_data_temp.iloc[current_player_row,judge_number_index+4]=average_score

            #重新儲存資料表,最後再賦值回去
            all_data_temp.to_excel('temp_data/'+str(self.race_name.text())+'_臨時儲存資料.xlsx', sheet_name='部分資訊', index=True) # index false為不寫入索引

            self.all_data_df=all_data_temp
            print(self.all_data_df)

            # #清空分數框         
            # for show_i in range(1,judge_number+1):
            #     judgeone_score_input_name="judgeone_score_input_"+str(show_i)
            #     judgeone_score_temp = self.race_going.findChild(QLineEdit,judgeone_score_input_name)
            #     judgeone_score_temp.clear()
            
            self.have_score_number=self.have_score_number+1 #儲存當前選手序號,只用於驗證選手是否棄權
            print("self.have_score_number=",self.have_score_number)

            return
        else:
            self.setQMessageBoxoneButtonTextENToCN("提示","請檢查後,繼續填寫",QMessageBox.Information)
            return


        return


    #單選按鈕繫結
    def func_radiobox_btnstate(self,btn):
        #輸出按鈕1與按鈕2的狀態,選中還是沒選中
        if btn.text()=='是':
            if btn.isChecked()==True:
                # print(btn.text()+"is selected")
                self.remove_score.setVisible(True) #初始設定隱藏
                self.remove_score_label_now.setVisible(True) #初始設定隱藏
            else:
                # print(btn.text()+"is deselected")
                return

        if btn.text()=="否":
            if btn.isChecked() == True:
                # print(btn.text() + "is selected")
                self.remove_score.setVisible(False) #初始設定隱藏
                self.remove_score_label_now.setVisible(False) #初始設定隱藏
                self.remove_score.setText("") #重新設定為空
            else:
                # print(btn.text() + "is deselected")
                return
    def setQMessageBoxtwoButtonTextENToCN(self,windowTitle, text,  qmessageIcon):
        """
        設定需要的QMessageBox的按鈕提示為中文
        :param qmessageIcon: 顯示圖示  例如QMessageBox.Question
        :param kwargs: 確定=QMessageBox.AcceptRole
        """
        msgBox = QMessageBox()
        msgBox.setWindowTitle(windowTitle)
        msgBox.setText(text)
        msgBox.setIcon(qmessageIcon)
        msgBox.setStandardButtons(QMessageBox.Yes | QMessageBox.No)
        buttonY = msgBox.button(QMessageBox.Yes)
        buttonY.setText('是')
        buttonN = msgBox.button(QMessageBox.No)
        buttonN.setText('否')
        ret=msgBox.exec_()
        return ret
    
    def setQMessageappENToCN(self,windowTitle, text,  qmessageIcon):
        """
        設定需要的QMessageBox的按鈕提示為中文
        :param qmessageIcon: 顯示圖示  例如QMessageBox.Question
        :param kwargs: 確定=QMessageBox.AcceptRole
        """
        msgBox = QMessageBox()
        msgBox.setWindowTitle(windowTitle)
        msgBox.setText(text)
        msgBox.setIcon(qmessageIcon)
        msgBox.setStandardButtons(QMessageBox.Yes | QMessageBox.No)
        buttonY = msgBox.button(QMessageBox.Yes)
        buttonY.setText('比賽暫停')
        buttonN = msgBox.button(QMessageBox.No)
        buttonN.setText('比賽結束')
        ret=msgBox.exec_()
        return ret


    def setQMessageBoxoneButtonTextENToCN(self,windowTitle, text,  qmessageIcon):
        """
        設定需要的QMessageBox的按鈕提示為中文
        :param qmessageIcon: 顯示圖示  例如QMessageBox.Question
        :param kwargs: 確定=QMessageBox.AcceptRole
        """
        msgBox = QMessageBox()
        msgBox.setWindowTitle(windowTitle)
        msgBox.setText(text)
        msgBox.setIcon(qmessageIcon)
        msgBox.setStandardButtons(QMessageBox.Yes)
        buttonY = msgBox.button(QMessageBox.Yes)
        buttonY.setText('是')
        msgBox.exec_()

    #根據輸入框來讀取資訊已經無誤
    def func_race_info(self):
        reply_one=self.setQMessageBoxtwoButtonTextENToCN('提示', '是否確認比賽準備資訊無誤?',QMessageBox.Question)

        if reply_one == QMessageBox.No:    
            self.setQMessageBoxoneButtonTextENToCN("提示","請繼續填寫",QMessageBox.Information)
            return

        #檢查是否有未填寫資料
        if self.race_name.text()=='' or self.judge_number.text()=='' or self.judge_namelist.toPlainText()=='' or self.player_number.text()==''  or self.player_namelist.toPlainText()=='' or self.music_namelist.toPlainText()=='':
            self.setQMessageBoxoneButtonTextENToCN("提示","有未填寫資料",QMessageBox.Information)
            return
        
        if self.remove_score.text()=='' and self.remove_yes_radiobox.isChecked()==True:
            self.setQMessageBoxoneButtonTextENToCN("提示","有未填寫資料",QMessageBox.Information)
            return
        #檢查評委數量是否足夠
        if  int(self.judge_number.text())!=len(self.judge_namelist.toPlainText().split('\n')):
            self.setQMessageBoxoneButtonTextENToCN("提示","評委數量與評委姓名數量不對應,請重新填寫",QMessageBox.Information)
            return
        
        #檢查選手數量是否足夠
        if  int(self.player_number.text())!=len(self.player_namelist.toPlainText().split('\n')):
            self.setQMessageBoxoneButtonTextENToCN("提示","選手數量與選手姓名數量不對應,請重新填寫",QMessageBox.Information)
            return
        
        #檢查曲目數量是否足夠
        if  int(self.player_number.text())!=len(self.music_namelist.toPlainText().split('\n')):
            self.setQMessageBoxoneButtonTextENToCN("提示","音樂數量與選手數量不對應,請重新填寫",QMessageBox.Information)
            return

        if reply_one == QMessageBox.Yes:    
            self.setQMessageBoxoneButtonTextENToCN("提示","比賽準備資訊填寫成功",QMessageBox.Information)          
            self.score_table.setColumnCount(3)
            self.score_table.setRowCount(int(self.player_number.text()))
            column_namelist_temp=["抽籤序號","選手姓名","曲目名稱"]
            self.score_table.setHorizontalHeaderLabels(column_namelist_temp) #設定行表頭

            player_namelist_temp=self.player_namelist.toPlainText().split('\n')
            music_namelist_temp=self.music_namelist.toPlainText().split('\n')
            for i in range(int(self.player_number.text())):
                self.score_table.setItem(i,0, QTableWidgetItem(str(i+1)))
                self.score_table.setItem(i,1, QTableWidgetItem(player_namelist_temp[i]))
                self.score_table.setItem(i,2, QTableWidgetItem(music_namelist_temp[i]))

            #設定按鈕可用
            self.race_start.setEnabled(True)
            self.save_info.setEnabled(True)

            #給設定自適應寬度
            self.score_table.resizeColumnToContents(0)
            self.score_table.resizeColumnToContents(1)
            self.score_table.resizeColumnToContents(2)
            return
        return

    #這是按照全新比賽的操作
    def func_race_start(self):
        #先將讀取的資料儲存起來,以tablewight資料表資訊為準
        player_index=[]
        player_name=[]
        music_name=[]
        for qtable_row in range(int(self.player_number.text())):
            player_index.append(self.score_table.item(qtable_row,0).text())  #獲取某行某列item中的x資訊
            player_name.append(self.score_table.item(qtable_row,1).text())  #獲取某行某列item中的x資訊
            music_name.append(self.score_table.item(qtable_row,2).text())  #獲取某行某列item中的x資訊
        
        judge_all_list=[]
        for qtable_column in range(int(self.judge_number.text())):
            judge_one_list=[' ']*int(self.player_number.text()) #將列資料全部填充為空格
            judge_all_list.append(judge_one_list)

        # creating the DataFrame
        all_data = pd.DataFrame(list(zip(player_index, player_name, music_name))) 

        all_data.columns =['抽籤序號', '選手姓名', '曲目名稱'] #設定列名

        judge_namelist_temp=self.judge_namelist.toPlainText().split('\n')
        for qtable_column in range(int(self.judge_number.text())):
            judge_one_list=[' ']*int(self.player_number.text()) #將列資料全部填充為空格
            judge_column_name=judge_namelist_temp[qtable_column]+":"+str(qtable_column+1)+"號評委"
            all_data[judge_column_name]=judge_one_list

        #增加最高分,最低分列 ,增加實際得分列
        if self.remove_yes_radiobox.isChecked()==True:
            max_one_list=[' ']*int(self.player_number.text()) #將列資料全部填充為空格
            all_data['最高分']=max_one_list

            min_one_list=[' ']*int(self.player_number.text()) #將列資料全部填充為空格
            all_data['最低分']=min_one_list

            visual_one_list=[-1]*int(self.player_number.text()) #將列資料全部填充為空格
            all_data['實得分']=visual_one_list

            index_one_list=[' ']*int(self.player_number.text()) #將列資料全部填充為空格
            all_data['最終排名']=index_one_list

            remove_score_str=self.remove_score.text()
            self.remove_score_number=int(self.remove_score.text())
            remove_one_list=[remove_score_str]*int(self.player_number.text()) #將列資料全部填充為空格
            all_data['去掉幾個最高分']=remove_one_list
        else:
            visual_one_list=[-1]*int(self.player_number.text()) #將列資料全部填充為空格
            all_data['實得分']=visual_one_list

            index_one_list=[' ']*int(self.player_number.text()) #將列資料全部填充為空格
            all_data['最終排名']=index_one_list

            remove_one_list=['0']*int(self.player_number.text()) #將列資料全部填充為空格
            all_data['去掉幾個最高分']=remove_one_list

        all_data['抽籤序號']=all_data['抽籤序號'].astype(int)
        all_data=all_data.sort_values(by=['抽籤序號']) #按照抽籤序號排序
        all_data=all_data.reset_index(drop=True) #重新排列一下索引

        all_data.to_excel('temp_data/'+str(self.race_name.text())+'_臨時儲存資料.xlsx', sheet_name='部分資訊', index=True) # index false為不寫入索引
        self.all_data_df=all_data

        #介面展示與隱藏
        self.race_prepare.setVisible(False) #初始設定隱藏
        self.race_going.setVisible(True) #初始設定隱藏

        #設定比賽名稱
        self.race_going_name.setText(self.race_name.text())

        # 展示當前選手資訊,需要讀取資料表的1號來展示
        self.current_player.setText("當前選手:1號選手"+str(all_data.loc[0,'選手姓名']))

        #根據評委數量來顯示評委框
        judge_number=int(self.judge_number.text())
        judge_one_namelist=self.judge_namelist.toPlainText().split('\n')
        for show_i in range(1,judge_number+1):
            judge_one_label_name="judge_one_label_"+str(show_i)
            judge_one_temp = self.race_going.findChild(QLabel,judge_one_label_name)
            #設定評委label的text
            judge_one_temp.setText(judge_one_namelist[show_i-1]+":"+str(show_i)+"號評委")
            judge_one_temp.setVisible(True)

            judgeone_score_input_name="judgeone_score_input_"+str(show_i)
            judgeone_score_temp = self.race_going.findChild(QLineEdit,judgeone_score_input_name)
            judgeone_score_temp.setVisible(True)

        #根據是否需要去掉最高分和最低分來展示
        if self.remove_yes_radiobox.isChecked()==True:
            #去掉了最高分和最低分,那麼就顯示所有的
            for show_i in range(1,5):
                judge_com_label_name="judge_com_label_"+str(show_i)
                judge_com_temp = self.race_going.findChild(QLabel,judge_com_label_name)
                judge_com_temp.setVisible(True)
        else:
            #不去掉,則只顯示,實際得分
            self.judge_com_average_label.setVisible(True)
            self.judge_com_average.setVisible(True)
        
        return

    #下一個選手
    def func_next_player(self):
        #獲取資料,儲存這個選手的得分到臨時表格中
        all_data_temp=self.all_data_df
        print(self.all_data_df)
        
        #先詢問是否計算最終得分,獲取輸入框資訊,計算得分,然後展示出來,展示出來之後將資訊儲存到臨時資料表中
        reply_one=self.setQMessageBoxtwoButtonTextENToCN('提示', '是否跳到下一個選手?',QMessageBox.Question)
        if reply_one == QMessageBox.Yes:    
            #先判斷選手是否是棄權
            #確定當前計算的是哪個選手,至少有一個評委
            current_player_row=0
            #找到第一個未計分的選手
            player_row=int(all_data_temp.shape[0])
            print("player_row=",player_row)
            for player_row_index in range(0,player_row):
                print(str(all_data_temp.iloc[player_row_index,int(all_data_temp.shape[1])-3]))
                print(str(all_data_temp.iloc[player_row_index,int(all_data_temp.shape[1])-3])=='-1')
                if str(all_data_temp.iloc[player_row_index,int(all_data_temp.shape[1])-3])=='-1' or str(all_data_temp.iloc[player_row_index,int(all_data_temp.shape[1])-3])=='-1.0':
                    current_player_row=player_row_index
                    break
                current_player_row=player_row_index

            self.have_score_number=current_player_row+1
            print("current_player_row=",current_player_row)
            print("player_row=",player_row)
            print("self.have_score_number=",self.have_score_number)

            if self.have_score_number==player_row:
                #這時候比賽就提示已經統計完所有選手分數
                self.setQMessageBoxoneButtonTextENToCN("提示","已統計完所有選手分數",QMessageBox.Information)  
                self.current_player.setText("本場比賽所有選手已比賽完畢,請退出程式")
                #儲存方法在有最高分和沒有最高分時有所不同,有
                judge_number=0
                if int(all_data_temp.loc[0,'去掉幾個最高分'])>0:
                    judge_number=int(all_data_temp.shape[1])-8
                else:
                    judge_number=int(all_data_temp.shape[1])-6
                #清空分數框
                for show_i in range(1,judge_number+1):
                    judgeone_score_input_name="judgeone_score_input_"+str(show_i)
                    judgeone_score_temp = self.race_going.findChild(QLineEdit,judgeone_score_input_name)
                    judgeone_score_temp.clear()

                    # judgeone_score_temp.setReadOnly(False)  #恢復成可修改

                if int(all_data_temp.loc[0,'去掉幾個最高分'])>0:
                    #設定最高分
                    self.judge_com_max.setText("最高分: ")
                    #設定最低分
                    self.judge_com_min.setText("最低分: ")
                    #設定最終分數
                    self.judge_com_average.setText(str(''))
                else:
                    #設定最終分數
                    self.judge_com_average.setText(str(''))

                self.judgeone_score_1.setFocus() #設定游標

                #設定按鈕不可點選
                self.next_player.setEnabled(False)
                #選手棄權按鈕
                self.player_quit.setEnabled(False)


                return
            else:
                judge_number=0
                if int(all_data_temp.loc[0,'去掉幾個最高分'])>0:
                    judge_number=int(all_data_temp.shape[1])-8
                else:
                    judge_number=int(all_data_temp.shape[1])-6
                #current_player_row表示當前第一個空的資料選手序號,self.have_score_number表示已經填寫的選手資料序號,
                # 如果不一樣,說明這個選手棄權了,需要把所有資料填寫完畢
                # 如果計算資料表裡的和當前的一樣,那就說明沒有棄權
                print("self.have_score_number=",self.have_score_number)
                print("current_player_row=",current_player_row)
                #正常切換,只需要重新設定一些資訊即可
                #清空分數框
                for show_i in range(1,judge_number+1):
                    judgeone_score_input_name="judgeone_score_input_"+str(show_i)
                    judgeone_score_temp = self.race_going.findChild(QLineEdit,judgeone_score_input_name)
                    judgeone_score_temp.clear()

                    judgeone_score_temp.setReadOnly(False)  #恢復成可修改
                
                if int(all_data_temp.loc[0,'去掉幾個最高分'])>0:
                    #重新設定文字資訊
                    #設定下一個選手
                    self.current_player.setText("當前選手:"+str(current_player_row+1)+"號選手")
                    #設定最高分
                    self.judge_com_max.setText("最高分: ")
                    #設定最低分
                    self.judge_com_min.setText("最低分: ")
                    #設定最終分數
                    self.judge_com_average.setText(str(''))
                else:
                    #設定下一個選手
                    self.current_player.setText("當前選手:"+str(current_player_row+1)+"號選手")
                    #設定最終分數
                    self.judge_com_average.setText(str(''))
                
                self.judgeone_score_1.setFocus() #設定游標
                return
              
            return
        else:
            self.setQMessageBoxoneButtonTextENToCN("提示","使用者取消操作",QMessageBox.Information)
            return

        return

    def func_player_quit(self):
        #獲取資料,儲存這個選手的得分到臨時表格中
        all_data_temp=self.all_data_df
        print(self.all_data_df)
        current_player_row=0
        #先詢問是否計算最終得分,獲取輸入框資訊,計算得分,然後展示出來,展示出來之後將資訊儲存到臨時資料表中
        reply_one=self.setQMessageBoxtwoButtonTextENToCN('提示', '當前選手是否棄權?',QMessageBox.Question)
        if reply_one == QMessageBox.Yes:    
            #選手棄權
            judge_number=0
            if int(all_data_temp.loc[0,'去掉幾個最高分'])>0:
                judge_number=int(all_data_temp.shape[1])-8
            else:
                judge_number=int(all_data_temp.shape[1])-6
            #清空分數框
            for show_i in range(1,judge_number+1):
                judgeone_score_input_name="judgeone_score_input_"+str(show_i)
                judgeone_score_temp = self.race_going.findChild(QLineEdit,judgeone_score_input_name)
                judgeone_score_temp.clear()

            #找到第一個未計分的選手
            player_row=int(all_data_temp.shape[0])
            print("player_row=",player_row)
            for player_row_index in range(0,player_row):
                print(str(all_data_temp.iloc[player_row_index,int(all_data_temp.shape[1])-3]))
                print(str(all_data_temp.iloc[player_row_index,int(all_data_temp.shape[1])-3])=='-1')
                if str(all_data_temp.iloc[player_row_index,int(all_data_temp.shape[1])-3])=='-1' or str(all_data_temp.iloc[player_row_index,int(all_data_temp.shape[1])-3])=='-1.0':
                    current_player_row=player_row_index
                    break
                current_player_row=player_row_index

            self.have_score_number=current_player_row
            if self.have_score_number==player_row:
                #這時候比賽就提示已經統計完所有選手分數
                self.setQMessageBoxoneButtonTextENToCN("提示","已統計完所有選手分數",QMessageBox.Information)

                #設定按鈕不可點選
                self.next_player.setEnabled(False)
                #選手棄權按鈕
                self.player_quit.setEnabled(False)

                return
            else:
                #儲存方法在有最高分和沒有最高分時有所不同,有
                if int(all_data_temp.loc[0,'去掉幾個最高分'])>0:
                #將這裡面的資料進行覆蓋  操作的是save_score_list,score_list_temp_max,score_list_temp_min
                    for judge_number_index in range(0,judge_number):
                        print(judge_number_index)
                        all_data_temp.iloc[current_player_row,judge_number_index+3]=0  
                    
                    all_data_temp.iloc[current_player_row,judge_number_index+4]=0 
                    all_data_temp.iloc[current_player_row,judge_number_index+5]=0
                    all_data_temp.iloc[current_player_row,judge_number_index+6]=0
                else:
                    for judge_number_index in range(0,judge_number):
                        all_data_temp.iloc[current_player_row,judge_number_index+3]=0   
                    
                    all_data_temp.iloc[current_player_row,judge_number_index+4]=0

                print("棄權後all_data_temp=",all_data_temp)
                #重新儲存資料表,最後再賦值回去
                all_data_temp.to_excel('temp_data/'+str(self.race_name.text())+'_臨時儲存資料.xlsx', sheet_name='部分資訊', index=True) # index false為不寫入索引
                self.all_data_df=all_data_temp

                self.have_score_number=self.have_score_number+1
                self.setQMessageBoxoneButtonTextENToCN("提示",str(current_player_row+1)+"號選手"+str(all_data_temp.loc[current_player_row,'選手姓名'])+"棄權成功,馬上跳到下一個選手",QMessageBox.Information)


                if self.have_score_number==player_row:
                    #這時候比賽就提示已經統計完所有選手分數
                    self.setQMessageBoxoneButtonTextENToCN("提示","已統計完所有選手分數",QMessageBox.Information)
                    self.current_player.setText("本場比賽所有選手已比賽完畢,請退出程式")
                    #儲存方法在有最高分和沒有最高分時有所不同,有
                    #清空分數框
                    for show_i in range(1,judge_number+1):
                        judgeone_score_input_name="judgeone_score_input_"+str(show_i)
                        judgeone_score_temp = self.race_going.findChild(QLineEdit,judgeone_score_input_name)
                        judgeone_score_temp.clear()

                    if int(all_data_temp.loc[0,'去掉幾個最高分'])>0:
                        #設定最高分
                        self.judge_com_max.setText("最高分: ")
                        #設定最低分
                        self.judge_com_min.setText("最低分: ")
                        #設定最終分數
                        self.judge_com_average.setText(str(''))
                    else:
                        #設定最終分數
                        self.judge_com_average.setText(str(''))

                    self.judgeone_score_1.setFocus() #設定游標

                    #設定按鈕不可點選
                    self.next_player.setEnabled(False)
                    #選手棄權按鈕
                    self.player_quit.setEnabled(False)

                    return
                else:
                    #跳轉到下一個選手
                    if int(all_data_temp.loc[0,'去掉幾個最高分'])>0:
                        self.current_player.setText("當前選手:"+str(current_player_row+2)+"號選手"+str(all_data_temp.loc[current_player_row+1,'選手姓名']))
                        #設定最高分
                        self.judge_com_max.setText("最高分: ")
                        #設定最低分
                        self.judge_com_min.setText("最低分: ")
                        #設定最終分數
                        self.judge_com_average.setText(str(''))
                    else:
                        #設定下一個選手
                        self.current_player.setText("當前選手:"+str(current_player_row+2)+"號選手"+str(all_data_temp.loc[current_player_row+1,'選手姓名']))
                        #設定最終分數
                        self.judge_com_average.setText(str(''))

                    self.judgeone_score_1.setFocus() #設定游標
                    


                return
        else:
            self.setQMessageBoxoneButtonTextENToCN("提示","使用者取消操作",QMessageBox.Information)
            return

    #結束比賽
    def func_exit_race(self):
        #獲取資料,儲存這個選手的得分到臨時表格中
        all_data_temp=self.all_data_df
        print(self.all_data_df)
        
        reply_zero=self.setQMessageappENToCN('提示', '請選擇退出程式的原因?',QMessageBox.Question)
        if reply_zero == QMessageBox.Yes:
            reply_one=self.setQMessageBoxtwoButtonTextENToCN('提示', '是否確認選擇比賽暫停?',QMessageBox.Question)
            if reply_one == QMessageBox.Yes: 
                self.setQMessageBoxoneButtonTextENToCN("提示","比賽暫停,臨時資料儲存成功",QMessageBox.Information)
                sys.exit(0)
                return
            else:
                self.setQMessageBoxoneButtonTextENToCN("提示","使用者取消操作",QMessageBox.Information)
                return
            return
        else:
            reply_two=self.setQMessageBoxtwoButtonTextENToCN('提示', '是否確認選擇比賽結束?',QMessageBox.Question)
            if reply_two == QMessageBox.Yes: 
                #匯出資料,清空臨時表
                all_data_temp=all_data_temp.sort_values(by=['實得分'],ascending=False) #按照抽籤序號排序
                all_data_temp=all_data_temp.reset_index(drop=True) #重新排列一下索引
                
                player_row=int(all_data_temp.shape[0])
                print("player_row=",player_row)
                for player_row_index in range(0,player_row):
                    all_data_temp.iloc[player_row_index,int(all_data_temp.shape[1])-2]=player_row_index+1

                all_data_temp.to_excel('save_data/'+str(self.race_name.text())+'_最終資料全部備份版.xlsx', sheet_name='部分資訊', index=True) # index false為不寫入索引
                #保留特定資料
                all_data_temp_new = all_data_temp[['抽籤序號', '選手姓名', '曲目名稱','實得分','最終排名']]
                
                # 建立一個新的文件
                doc_part=docx.Document()
                # 新增標題
                para_heading=doc_part.add_heading(str(self.race_name.text()), 5)
                para_heading.alignment=docx.enum.text.WD_ALIGN_PARAGRAPH.CENTER#設定為左對齊


                # 新增表格
                table_part = doc_part.add_table(rows=all_data_temp_new.shape[0]+1, cols=all_data_temp_new.shape[1])

                # 新增表頭
                hdr_cells = table_part.rows[0].cells
                for i in range(all_data_temp_new.shape[1]):
                    hdr_cells[i].text = all_data_temp_new.columns[i]

                # 新增每一行資料
                for i in range(all_data_temp_new.shape[0]):
                    row_cells = table_part.rows[i+1].cells
                    for j in range(all_data_temp_new.shape[1]):
                        row_cells[j].text = str(all_data_temp_new.values[i,j])

                # 儲存檔案
                doc_part.save('save_data/'+str(self.race_name.text())+'_最終資料簡潔版.docx')
                # del_files("temp_data/")
                self.setQMessageBoxoneButtonTextENToCN("提示","最終資料匯出成功,本次比賽臨時資料已清除",QMessageBox.Information)
                sys.exit(0)
                return
            else:
                self.setQMessageBoxoneButtonTextENToCN("提示","使用者取消操作",QMessageBox.Information)
                return
            return

        return

    #根據檔案來讀取資訊,這個是不一樣的,最後寫才對,這個繼續前次比賽,比賽的資訊設定與全新比賽不相同
    def func_continue_race(self):
        #先是詢問是否繼續上次比賽
        reply_one=self.setQMessageBoxtwoButtonTextENToCN('提示', '是否繼續上次比賽?',QMessageBox.Question)
        if reply_one == QMessageBox.Yes:        
            folderName, _ = QFileDialog.getOpenFileName(self, "選擇xlsx檔案", "", "*.xlsx")        
            race_name=folderName.split("/")[-1].split("_")[0]
            self.race_name.setText(race_name)
            self.all_data_df=pd.read_excel('temp_data/'+folderName.split("/")[-1],index_col=0)
            
            all_data_temp=self.all_data_df

            #介面展示與隱藏
            self.race_prepare.setVisible(False) #初始設定隱藏
            self.race_going.setVisible(True) #初始設定隱藏

            #設定比賽名稱
            self.race_going_name.setText(race_name)

            #設定選手初值
            current_player_row=0
            #找到第一個未計分的選手
            player_row=int(all_data_temp.shape[0])
            print("player_row=",player_row)
            for player_row_index in range(0,player_row):
                print(str(all_data_temp.iloc[player_row_index,int(all_data_temp.shape[1])-3]))
                print(str(all_data_temp.iloc[player_row_index,int(all_data_temp.shape[1])-3])=='-1')
                if str(all_data_temp.iloc[player_row_index,int(all_data_temp.shape[1])-3])=='-1' or str(all_data_temp.iloc[player_row_index,int(all_data_temp.shape[1])-3])=='-1.0':
                    current_player_row=player_row_index
                    break
                current_player_row=player_row_index

            self.have_score_number=current_player_row
            judge_number=0

            self.remove_score_number=int(all_data_temp.loc[0,'去掉幾個最高分'])
            
            #設定介面資訊:當前選手,是否展示實得分最高分,評委名字
            if int(all_data_temp.loc[0,'去掉幾個最高分'])>0:
                self.current_player.setText("當前選手:"+str(current_player_row+1)+"號選手")
                for show_i in range(1,5):
                    judge_com_label_name="judge_com_label_"+str(show_i)
                    judge_com_temp = self.race_going.findChild(QLabel,judge_com_label_name)
                    judge_com_temp.setVisible(True)
                #設定最高分
                self.judge_com_max.setText("最高分: ")
                #設定最低分
                self.judge_com_min.setText("最低分: ")
                #設定最終分數
                self.judge_com_average.setText(str(''))
                judge_number=int(all_data_temp.shape[1])-8
            else:
                #設定下一個選手
                self.current_player.setText("當前選手:"+str(current_player_row+1)+"號選手")
                self.judge_com_average_label.setVisible(True)
                self.judge_com_average.setVisible(True)
                #設定最終分數
                self.judge_com_average.setText(str(''))
                judge_number=int(all_data_temp.shape[1])-6

            judge_namelist=[column for column in all_data_temp]
            judge_one_namelist=judge_namelist[3:3+judge_number]
            for show_i in range(1,judge_number+1):
                judge_one_label_name="judge_one_label_"+str(show_i)
                judge_one_temp = self.race_going.findChild(QLabel,judge_one_label_name)
                #設定評委label的text
                judge_one_temp.setText(judge_one_namelist[show_i-1].split(":")[0]+":"+str(show_i)+"號評委")
                judge_one_temp.setVisible(True)

                judgeone_score_input_name="judgeone_score_input_"+str(show_i)
                judgeone_score_temp = self.race_going.findChild(QLineEdit,judgeone_score_input_name)
                judgeone_score_temp.setVisible(True)

        else:
            self.setQMessageBoxoneButtonTextENToCN("提示","使用者取消操作",QMessageBox.Information)
        return


if __name__ == '__main__':
    app=QApplication(sys.argv)  
    w = MyWindow()
    w.ui.show()
    app.exec()

程式打包成exe

指令 安裝pyinstall庫

檔案目錄
根路徑
	getscore.py
	assets
		xxx.ui
	save_data
	temp_data
	

pyinstaller -F -w getscore.py --add-data ".\\assets\\*;.\\assets"

參考文章

感謝以下作者的知識分享

PyQt入門教程 - 隨筆分類 - 鍋邊糊 - 部落格園 (cnblogs.com)

【創作不易,望點贊收藏,若有疑問,請留言,謝謝】

相關文章