#coding=utf-8import os,sys,re,time import pygame import random from win32api import GetSystemMetrics from tkinter import messageboxpygame.init() pygame.display.set_caption("我的控件")percent = 0.6 screen_width = GetSystemMetrics(0) screen_height = GetSystemMetrics(1) window_width = int(screen_width*percent) window_height = int(screen_height*percent)dt = 0 clock = pygame.time.Clock()screen = pygame.display.set_mode((window_width, window_height))#停止处理输入法事件 pygame.key.stop_text_input()def showMsg(msg):messagebox.showinfo('提示信息', msg)class Button:def __init__(self, x, y, w, h):self.x = xself.y = yself.w = wself.h = hself.color = 'gray'self.text = '按钮'self.text_color = 'black'self.text_size = 12self.border_width = 1self.border_color = 'black'self.font_path = os.path.join(os.path.dirname(sys.argv[0]), 'simsun.ttc')self.my_font = pygame.font.Font(self.font_path, self.text_size)def setColor(self, color):self.color = colordef setText(self, text):self.text = textdef getText(self):return self.textdef setTextColor(self, text_color):self.text_color = text_colordef setTextSize(self, text_size):self.text_size = text_sizeself.my_font = pygame.font.Font(self.font_path, self.text_size)def setBorderWidth(self, border_width):self.border_width = border_widthdef setBorderColor(self, border_color):self.border_color = border_colordef draw(self, win):pygame.draw.rect(win, self.color, (self.x, self.y, self.w, self.h))if self.border_width > 0:pygame.draw.rect(win, self.border_color, (self.x, self.y, self.w, self.h), self.border_width)text = self.my_font.render(self.text, True, self.text_color)myx = self.x + (self.w - text.get_width()) / 2myy = self.y + (self.h - text.get_height()) / 2win.blit(text, (myx, myy))def click(self, event):if event.type == pygame.MOUSEBUTTONDOWN:if self.x + self.w > event.pos[0] > self.x and self.y + self.h > event.pos[1] > self.y:return Truereturn Falseclass Label:def __init__(self, x, y, w, h):self.x = xself.y = yself.w = wself.h = hself.color = 'white'self.text = ''self.text_color = 'black'self.text_size = 12self.border_width = 0self.border_color = ''self.font_path = os.path.join(os.path.dirname(sys.argv[0]), 'simsun.ttc')self.my_font = pygame.font.Font(self.font_path, self.text_size)def setColor(self, color):self.color = colordef setText(self, text):self.text = textdef getText(self):return self.textdef setTextColor(self, text_color):self.text_color = text_colordef setTextSize(self, text_size):self.text_size = text_sizeself.my_font = pygame.font.Font(self.font_path, self.text_size)def setBorderWidth(self, border_width):self.border_width = border_widthdef setBorderColor(self, border_color):self.border_color = border_colordef getCharWH(self):padding_percent_width = 0.3padding_percent_height = 0.3test_text1 = '测试字符串'test_text2 = self.my_font.render(test_text1, True, self.text_color)char_width = test_text2.get_width() / len(test_text1)char_height = test_text2.get_height()padding_width = char_width * padding_percent_widthpadding_height = char_height * padding_percent_heightmax_field_num = int((self.w - padding_width * 2) / char_width)return (char_height, padding_width, padding_height, max_field_num)def getTrueLines(self, max_field_num):texts = self.text.split("\n")k = 0for i,mytext in enumerate(texts):while len(mytext) > max_field_num:submytext = mytext[0:max_field_num]mytext = mytext[max_field_num:]k += 1k += 1return k+1def draw(self, win):(char_height, padding_width, padding_height, max_field_num) = self.getCharWH()lineNum = self.getTrueLines(max_field_num)if lineNum * char_height > self.h:self.h = lineNum * char_heightpygame.draw.rect(win, self.color, (self.x, self.y, self.w, self.h))if self.border_width > 0:pygame.draw.rect(win, self.border_color, (self.x, self.y, self.w, self.h), self.border_width)texts = self.text.split("\n")k = 0for i,mytext in enumerate(texts):while len(mytext) > max_field_num:submytext = mytext[0:max_field_num]subtext = self.my_font.render(submytext, True, self.text_color)submyx = self.x + padding_widthsubmyy = self.y + padding_height + char_height * kwin.blit(subtext, (submyx, submyy))mytext = mytext[max_field_num:]k += 1text = self.my_font.render(mytext, True, self.text_color)myx = self.x + padding_widthmyy = self.y + padding_height + char_height * kwin.blit(text, (myx, myy))k += 1class TextArea:startx = 0endx = 0starty = 0endy = 0padding_width = 0padding_height = 0char_width = 0char_height = 0max_field_num = 0collbar_color = 'gray'collbar_bgcolor = 'lightgray'collbar_width_x = 0collbar_height_x = 5collbar_offset_x = 0collbar_percent_x = 0dragging_x = Falsecollbar_width_y = 5collbar_height_y = 0collbar_offset_y = 0collbar_percent_y = 0dragging_y = Falseline_wrap = Falsedef __init__(self, x, y, w, h, text, text_size = 12):self.x = xself.y = yself.w = wself.h = hself.color = 'white'self.text = textself.text_color = 'black'self.text_size = text_sizeself.border_width = 0self.border_color = ''self.font_path = os.path.join(os.path.dirname(sys.argv[0]), 'simsun.ttc')self.my_font = pygame.font.Font(self.font_path, self.text_size)self.getCharWH()def setColor(self, color):self.color = colordef setText(self, text):self.text = textself.getCharWH()def getText(self):return self.textdef setTextColor(self, text_color):self.text_color = text_colordef setTextSize(self, text_size):self.text_size = text_sizeself.my_font = pygame.font.Font(self.font_path, self.text_size)self.getCharWH()def setBorderWidth(self, border_width):self.border_width = border_widthdef setBorderColor(self, border_color):self.border_color = border_colordef getCharWH(self):padding_percent_width = 0.3padding_percent_height = 0.3test_text1 = '测试字符串'test_text2 = self.my_font.render(test_text1, True, self.text_color)self.char_width = test_text2.get_width() / len(test_text1)self.char_height = test_text2.get_height()self.padding_width = self.char_width * padding_percent_widthself.padding_height = self.char_height * padding_percent_heightself.max_field_num = self.getMaxFieldNum()showLineNum = self.getShowLineNum()totalLineNum = self.getTotalLineNum()print(showLineNum)print(totalLineNum)print()self.collbar_percent_y = showLineNum / totalLineNumif totalLineNum * self.char_height + 2 * self.padding_height+self.collbar_height_x > self.h:self.collbar_height_y = self.collbar_percent_y * (self.h - self.padding_height * 2-self.collbar_height_x)showFieldNum = self.getShowFieldNum()totalFieldNum = self.getTotalFieldNum()self.collbar_percent_x = showFieldNum / totalFieldNumif totalFieldNum * self.char_width + 2 * self.padding_width+self.collbar_width_y > self.w:self.collbar_width_x = self.collbar_percent_x * (self.w - self.padding_width * 2-self.collbar_width_y)#计算每行多少个字def getMaxFieldNum(self):num = 0if self.line_wrap == True:#折行时按控件宽度计算num = int((self.w - self.padding_width * 2 - self.collbar_width_y) / self.char_width)else:#不折行时按最长的行所含字符算texts = self.text.split("\n")for text in texts:if len(text) > num:num = len(text)return num#计算可以一次性展示的行数def getShowLineNum(self):lostHeight = self.h - 2 * self.padding_height;num = int(lostHeight // self.char_height)return num#计算所有行数def getTotalLineNum(self):texts = self.text.split("\n")if self.line_wrap == True:k = 0for i,mytext in enumerate(texts):while len(mytext) > self.max_field_num:submytext = mytext[0:self.max_field_num]mytext = mytext[self.max_field_num:]k += 1k += 1return kelse:return len(texts)#计算可以一次性展示的列数def getShowFieldNum(self):lostWidth = self.w - 2 * self.padding_width - self.collbar_width_y;num = int(lostWidth // self.char_width)return num#计算最长的行的列数def getTotalFieldNum(self):num = 0if self.line_wrap == True:#折行时按控件宽度计算num = int((self.w - self.padding_width * 2 - self.collbar_width_y) / self.char_width)else:#不折行时按最长的行所含字符算texts = self.text.split("\n")for text in texts:if len(text) > num:num = len(text)return numdef getTrueLineTexts(self):res = []texts = self.text.split("\n")k = 0for i,mytext in enumerate(texts):while len(mytext) > self.max_field_num:submytext = mytext[0:self.max_field_num]res.append(submytext)mytext = mytext[self.max_field_num:]k += 1k += 1res.append(mytext)return resdef draggingyMe(self, event):if event.type == pygame.MOUSEBUTTONDOWN:if self.x + self.w > event.pos[0] > self.x and self.y + self.h > event.pos[1] > self.y:self.dragging_x = Trueself.startx = event.pos[0]self.dragging_y = Trueself.starty = event.pos[1]elif event.type == pygame.MOUSEBUTTONUP:if self.x + self.w > event.pos[0] > self.x and self.y + self.h > event.pos[1] > self.y:self.dragging_x = Falseself.endx = event.pos[0]self.dragging_y = Falseself.endy = event.pos[1]elif event.type == pygame.MOUSEMOTION:if self.x + self.w > event.pos[0] > self.x and self.y + self.h > event.pos[1] > self.y:self.endx = event.pos[0]self.endy = event.pos[1]if self.dragging_x and self.collbar_width_x > 0:maxoffset = self.w - self.padding_width * 2 - self.collbar_width_y - self.collbar_width_xoffset = self.endx - self.startxif offset <= 0:self.collbar_offset_x = 0elif offset >= maxoffset:self.collbar_offset_x = maxoffsetelse:self.collbar_offset_x = offsetif self.dragging_y and self.collbar_height_y > 0:maxoffset = self.h - self.padding_height * 2 - self.collbar_height_x - self.collbar_height_yoffset = self.endy - self.startyif offset <= 0:self.collbar_offset_y = 0elif offset >= maxoffset:self.collbar_offset_y = maxoffsetelse:self.collbar_offset_y = offsetdef draw(self, win):pygame.draw.rect(win, self.color, (self.x, self.y, self.w, self.h))if self.border_width > 0:pygame.draw.rect(win, self.border_color, (self.x, self.y, self.w, self.h), self.border_width)#右侧滑动条if self.collbar_height_y > 0:pygame.draw.rect(win, self.collbar_bgcolor, (self.x+self.w-self.collbar_width_y-self.padding_width, self.y+self.padding_height, self.collbar_width_y, self.h-2*self.padding_height))pygame.draw.rect(win, self.collbar_color, (self.x+self.w-self.collbar_width_y-self.padding_width, self.y+self.padding_height+self.collbar_offset_y, self.collbar_width_y, self.collbar_height_y))#左侧滑动条if self.collbar_width_x > 0:pygame.draw.rect(win, self.collbar_bgcolor, (self.x+self.padding_width, self.y+self.h-self.padding_height-self.collbar_height_x, self.w-2*self.padding_width-self.collbar_width_y, self.collbar_height_x))pygame.draw.rect(win, self.collbar_color, (self.x+self.padding_width+self.collbar_offset_x, self.y+self.h-self.padding_height-self.collbar_height_x, self.collbar_width_x, self.collbar_height_x))test_texts = self.getTrueLineTexts()#显示哪些行cutPreLineNum = int(self.collbar_offset_y / self.collbar_percent_y // self.char_height)test_texts = test_texts[cutPreLineNum:]#显示哪些列showFieldNum = self.getShowFieldNum()cutPreFieldNum = int(self.collbar_offset_x / self.collbar_percent_x // self.char_width)for i,test_text in enumerate(test_texts):test_texts[i] = test_text[cutPreFieldNum:cutPreFieldNum+showFieldNum]texts = '\n'.join(test_texts).split("\n")k = 0for i,mytext in enumerate(texts):while len(mytext) > self.max_field_num:submytext = mytext[0:self.max_field_num]subtext = self.my_font.render(submytext, True, self.text_color)submyx = self.x + self.padding_widthsubmyy = self.y + self.padding_height + self.char_height * kif submyy+self.char_height < self.y+self.h-self.collbar_height_x:win.blit(subtext, (submyx, submyy))mytext = mytext[self.max_field_num:]k += 1text = self.my_font.render(mytext, True, self.text_color)myx = self.x + self.padding_widthmyy = self.y + self.padding_height + self.char_height * kif myy+self.char_height < self.y+self.h-self.collbar_height_x:win.blit(text, (myx, myy))k += 1bt = Button(5, 5, 80, 25) bt.setText('测试按钮') bt.setColor('Brown') bt.setTextColor('Gold') bt.setBorderColor('Lime') bt.setBorderWidth(1)label_text = ''' 壹哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈壹 贰哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈贰 叁哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈叁 肆哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈肆 伍哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈伍 陆哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈陆 柒哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈柒 '''.strip() label = Label(115, 5, 400, 100) label.setColor('Maroon') label.setText(label_text) label.setTextSize(18) label.setBorderColor('Lime') label.setBorderWidth(1)my_text1 = ''' 壹哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈壹 贰哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈贰 叁哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈叁 肆哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈肆 伍哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈伍 陆哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈陆 柒哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈柒 '''.strip() textArea1 = TextArea(535, 5, 400, 145, my_text1, 18) textArea1.setColor('white') textArea1.setBorderColor('Lime') textArea1.setBorderWidth(1)my_text2 = ''' 壹哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈壹 贰哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈贰 叁哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈叁 肆哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈肆 伍哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈伍 陆哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈陆 柒哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈柒 '''.strip() textArea2 = TextArea(535, 175, 300, 105, my_text2, 14) textArea2.setColor('white') textArea2.setBorderColor('Lime') textArea2.setBorderWidth(1)running = True while running:for event in pygame.event.get():if event.type == pygame.QUIT:running = FalsetextArea1.draggingyMe(event)textArea2.draggingyMe(event)if bt.click(event):showMsg("%s被点击了" % bt.getText())keys_pressed = pygame.key.get_pressed()#ESC键if keys_pressed[pygame.K_ESCAPE]:running = Falsescreen.fill("purple")bt.draw(screen)label.draw(screen)textArea1.draw(screen)textArea2.draw(screen)#更新显示 pygame.display.flip()#pygame.display.update() dt = clock.tick(60) / 600pygame.quit()
效果: