Изображения портфеля кликабельныJavascript

Форум по Javascript
Ответить
Anonymous
 Изображения портфеля кликабельны

Сообщение Anonymous »

Работа над интерфейсом приложения-портфеля Beeware для Android с движком в стиле пары друзей — это тога. Я пытаюсь сделать некоторые изображения кликабельными. Значки кнопок недостаточно большие, и я не нашел способа сделать их больше. Кроме того, я не нашел способа наслаивания кнопок и изображений, который мы также исследовали, но теперь я считаю его невозможным, что заставило меня обратиться к последнему средству: веб-просмотру (это то, чего мы хотим как можно меньше). Пока что это работает (стиль не полностью отсортирован, но на данный момент это не такая уж большая проблема. В настоящее время, когда я нажимаю изображение в веб-просмотре, оно отправляет все нормально, но появляется веб-страница, недоступная в течение доли секунды. Чтобы кнопка работала, мне пришлось изменить URL-адрес в javascript на URL-адрес, который не существует, а затем сбросить его обратно на правильный.
Python:

Код: Выделить всё

assert 1 + 1 == 2

# --- IMPORTS ---

from typing import Callable
import httpx  # type:ignore
import toga  # type:ignore
from toga.style import Pack  # type:ignore
from toga.style.pack import COLUMN, ROW  # type:ignore
from toga.widgets import webview # type: ignore
import asyncio
import pathlib
import threading
import os
from socketserver import TCPServer
import json
from http.server import SimpleHTTPRequestHandler, HTTPServer
from datetime import datetime
import time

try:
import toga_android.libs.location  # type:ignore
print("Force location sucessful")
except Exception as e: # grr
print("Force location failed, ", e)

# --- CLASSES ---

class jsApp(toga.App):
def __init__(self, *args, **kwargs):
self.permission_granted = False
super().__init__(*args, **kwargs)
self.locationList:dict = {}  # used to store location data if player is a hunter
self.gui = GUI(self)

# -- ONSTART --
# gets perms on startup

async def on_start(self):
print("Location backend:", type(self.location))
print("Onstart:")
granted = await self.location.request_permission()
if not granted:
print("You denied location.  Please enable in settings")
self.permission_granted = False
return
if granted:
print("Permission granted!, getting current location")
self.permission_granted = True

# -- STARTUP --

def startup(self):
self.main_window = toga.MainWindow(title=self.formal_name)
self.main_window.content = self.gui.loadingScreen()

asyncio.create_task(self.on_start())  # gets perms for location date

async def on_running(self):
# wait for permission_granted (avoid race)
timeout = 10.0
waited = 0.0
while not getattr(self, "permission_granted", False) and waited < timeout:
await asyncio.sleep(0.1)
waited += 0.1
if not self.permission_granted:
print("Permission not granted before on_running finished waiting; skipping location calls")
else:
print("Before location grab")
asyncio.create_task(self.getCurrentLocation())
print("After location grab")

if localPlayerId[1] == "i":  # i for hider
asyncio.create_task(self.sleepyTime(10, self.serverUpdateLocation, True))
elif localPlayerId[1] == "u":  # u for hunter
asyncio.create_task(self.sleepyTime(recieveLocationEvery, self.serverSendLocations, True))
else:
print("Error: Something updated the ID")

# begins getting location every few seconds
asyncio.create_task(self.sleepyTime(getLocationEvery, self.getCurrentLocation, True))
self.main_window.content = self.gui.startupScreen()
self.main_window.show()

super().on_running()

# -- BUTTONS --

def submitButton(self, button):
global localPlayerId, currentIp
localPlayerId = self.gui.idInput.value
asyncio.create_task(self.endTimeGrab())
currentIp = self.gui.serverInput.value
currentIp = "https://"  + currentIp + ".ngrok-free.app"
print(localPlayerId)
print(currentIp)
self.main_window.content = self.gui.waitingRoomScreen()
self.main_window.show()
asyncio.get_running_loop().create_task(self.gameLoop())
# self.gameLoop()  # waiting room bypass

def dieButtomn (self, button):
self.main_window.content = self.gui.checkScreen()
self.main_window.show()

def hiderKilled(self, button):
asyncio.create_task(self.become_hunter())

def hiderSafe(self, button):
self.main_window.content = self.gui.hiderScreen()
self.main_window.show()

# -- SERVER INTERFACE --

# POST update-location
async def serverUpdateLocation(self):
print(localLat)
print(localLong)
print("Post request attempted")  # remove this for final build
try:
async with httpx.AsyncClient(verify = False) as client:
postAttempt =  await client.post(currentIp + "/update-location", json={
"playerId": localPlayerId,
"lat": localLat,
"long": localLong
})
self.updateStatusLabel(f"Server responds with: {postAttempt.json()}")
except Exception as e:
self.updateStatusLabel(f"Error within serverUpdateLocation: {e}")

# POST caught
async def serverCaught(self, id):
print("caught")
try:
async with httpx.AsyncClient(verify = False) as client:
postAttempt = await client.post(currentIp + "/caught", json={
"playerID": id
})
print(f"caught: server responds with {postAttempt.json()}")
except Exception as e:
print("error within serverCaught:", e)

# GET send-locations
async def serverSendLocations(self):
print("Get request attempted")  # remove this for final build
try:
async with httpx.AsyncClient(verify = False) as client:
getAttempt = await client.get(currentIp + "/send-locations")
self.locationList = getAttempt.json()
try:
# self.rebuild_hunter_markers()
# self.refreshMarkers()
pass
except Exception:
pass

print(getAttempt.json())  # remove this for final build
self.updateStatusLabel(f"Location: {getAttempt.json()}")
except Exception as e:
self.updateStatusLabel(f"Error: {e}")
print(f"Error within updateStatusLabel: {e}")
# here

# GET waiting
async def waitingRoom(self):
print("waiting room")
try:
async with httpx.AsyncClient(verify = False) as client:
while True:
print("waiting attempt")
getAttempt = await client.get(currentIp + "/waiting")
print(getAttempt)
if getAttempt.json().get("status") == "started":
print("game started")
await self.gameLoop()
return
await asyncio.sleep(1)
except Exception as e:
print("failed to connect to waiting room:", e)

# -- ASYNC --

async def sleepyTime(self, zzz : float, function : Callable = None, repeat : bool = False):
if function is None: # ??? None ->  not
await asyncio.sleep(zzz)
if repeat:
while True:
await asyncio.sleep(zzz)
await function()
else:
if function is None:
await asyncio.sleep(zzz)
else:
await asyncio.sleep(zzz)
await function(zzz)

def updateStatusLabel(self, text:str):
if hasattr(self.main_window, "statusLabel"):
self.gui.statusLabel.text = text
print(text)

async def endTimeGrab(self):
"""
Assumes time is in the format HHMM
"""
global endTime
endTime = self.gui.timeInput.value
print("end time grabbed:", endTime)

def hiderTimer(self):
global endTime
now = datetime.now()
currentTime = now.strftime("%H:%M:%S")
currentTime = currentTime.split(":")
hoursDifference = int(str(endTime)[0:2]) - int(currentTime[0])
minutesDifference = int(str(endTime)[2:]) - int(currentTime[1])
minutesDifference += hoursDifference * 60
minutesDifference -= 1
if int(currentTime[2]) != 0:
secondsDifference = 60 - int(currentTime[2])
else:
secondsDifference = 0
secondsDifference = str(secondsDifference)
if len(secondsDifference) == 1:
secondsDifference = "0" + secondsDifference
timer = str(minutesDifference) + ":" + secondsDifference
print(timer)
global localPlayerId
if hasattr(self, "timerLabel"):
self.timerLabel.text = timer
if hasattr(self.gui, "timerLabel"):
self.gui.timerLabel.text = timer

# sends a ping and checks perms
# bug in here where an error is thrown if location is missed
async def getCurrentLocation(self,*args, **kwargs):#
try:
print("Get current location ran")  # remove for final build
service = self.location
loc = await service.current_location()
if loc is not None:
print("current location might be:", loc)
print(loc.lat, loc.lng)
global localLat
global localLong
localLat = loc.lat
localLong = loc.lng
else:
print("Failed to get location")
except Exception as e:
print("Error within getCurrentLocation: ", e)

# -- GAME LOGIC --

async def become_hunter(self):
print("caught")
global localPlayerId
oldId = localPlayerId
localPlayerId = "uu"  + localPlayerId

while True:
try:
await self.serverCaught(oldId)
print("server connection sucessful")
break
except Exception as e:
print("failed to connect to server:", e)
asyncio.sleep(1)

print("gameloop 2")
await self.gameLoop()

async def waitingRoomBackend(self):
print("waiting room logic worked")
# basically this needs to run the waiting room logic
await self.waitingRoom()
# this did have some more stuff in it

async def gameLoop(self):
# phew this is a long time in the making
# logic for the game
print("gameloop ran")

async def hiderTimerLoop():
while True:
self.hiderTimer()
await asyncio.sleep(1)

def hider():
self.main_window.content = self.gui.hiderScreen()
self.main_window.show()
asyncio.create_task(hiderTimerLoop())

async def hunter():
print("hunterscreen")  # this never runs
# self.main_window.content = self.gui.hunterScreen()
# self.main_window.show()
# self.show_hunter_map()
# self.refreshMarkers()
global recieveLocationEvery
self.init_hunter_map()
await hiderTimerLoop()
await self.sleepyTime(recieveLocationEvery, self.refresh_hunter_markers, True)

global localPlayerId
if localPlayerId[1] == "i":  # i for hider
hider()
elif localPlayerId[1] == "u":  # u for hunter
print("hunter")
await hunter()
else:
print("?????")

# -- AI CODE --

def init_hunter_map(self):
import toga #type:ignore

print("Initializing hunter map...")

# Step 1: Start local server if not already running
if not hasattr(self, "local_port"):
self.start_local_server()

# Step 2: Create WebView
self.webview = toga.WebView(style = Pack(
flex = 1
))
print("WebView created")

# Step 3: Load map.html via http://
url = f"http://127.0.0.1:{self.local_port}/map.html"
print("Loading URL:", url)
self.webview.url = url

# Step 4:  Show it in the window
box = toga.Box(style = Pack(
flex = 1,
direction = COLUMN,
))

self.timerLabel = toga.Label("XX:XX", style = Pack(
background_color = "#282828",
color = "#9B9B9B",
text_align = "center",
flex = 1
))

box.add(self.timerLabel)
box.add(self.webview)

self.main_window.content = box
self.main_window.show()

print("Hunter map loaded.")

async def refresh_hunter_markers(self):
global currentIp
"""Fetch latest locations and update markers on the map."""
try:
async with httpx.AsyncClient() as client:
response = await client.get(f"{currentIp}/send-locations")
if response.status_code == 200:
locations = response.json()
js = f"refreshMarkers({json.dumps(locations)});"
self.webview.evaluate_javascript(js)
else:
print("Failed to fetch locations:", response.status_code)
except Exception as e:
print("Error refreshing hunter markers:", e)

def start_local_server(self):
def run_server():
# Try a list of candidate directories
candidates = []
try:
candidates.append(str(self.paths.app / "resources"))
except Exception:
pass
# add working dir fallback
candidates.append(os.getcwd())
chosen = None
for c in candidates:
try:
if os.path.isdir(c):
os.chdir(c)
chosen = c
break
except Exception:
pass
if chosen is None:
print("No valid resources directory found; local server won't run.")
return

with TCPServer(("127.0.0.1", 0), SimpleHTTPRequestHandler) as httpd:
self.local_port = httpd.server_address[1]
print(f"Local server running on port {self.local_port}, serving {chosen}")
httpd.serve_forever()

server_thread = threading.Thread(target=run_server, daemon=True)
server_thread.start()

class GUI:
def __init__(self, app):
self.app = app

self.hunter = toga.Icon("icons/hunter-128")

self.hider = toga.Icon("icons/hider-128")

image_path = self.app.paths.app / "resources" / "helloworld.png"
hiderPath = self.app.paths.app / "resources" / "hider.png"
hunterPath = self.app.paths.app / "resources" / "hunter.png"

self.image = toga.Image(image_path)
self.hiderImage = toga.Image(hiderPath)
self.hunterImage = toga.Image(hunterPath)

self.imgLabel = toga.ImageView(self.image, style= Pack(
width=78,
height=78,
justify_content="end"
))

self.hiderLabel = toga.ImageView(self.hiderImage, style= Pack(
width=150,
height=150,
))

self.hunterLabel = toga.ImageView(self.hunterImage, style= Pack(
width=150,
height=150,
))

async def hunterMessageHandler (self, webview, **kwargs):
global hunterID

lastUrl = None
defaultUrl = f"http://127.0.0.1:{self.app.local_port}/hunterButton.html"
while True:
await asyncio.sleep(0.01)

if not hasattr(self, "hunterView"):
continue

url = self.hunterView.url
if url != lastUrl:
lastUrl = url

if url == "toga://hunt":
self.hunterView.evaluate_javascript(f'window.location = "http://127.0.0.1:{self.app.local_port}/hunterButton.html"')
print("button clicked")
jsApp.become_hunter
print(f"url: {url}")
hunterID = "hunter"  + self.idInput.value
print(f"id: {hunterID}")
url = defaultUrl
print(f"url: {url}")
lastUrl = defaultUrl

def loadingScreen(self):
waitingLabel = toga.Label("Loading...", style = Pack(
padding = 10,
background_color = "#282828",
color = "#9B9B9B",
text_align = "center",
))

self.versionLabel = toga.Label("Version 4", style = Pack(
padding = 10,
background_color = "#141414",
color = "#9B9B9B",
text_align = "center",
))

self.versionBox = toga.Box(style = Pack(
direction = COLUMN,
background_color = "#141414",
height=50,
justify_content="end"
))
self.versionBox.add(self.versionLabel)

loadingScreen = toga.Box(style = Pack(
direction = COLUMN,
background_color = "#141414"
))

loadingScreen.add(waitingLabel)
loadingScreen.add(self.versionBox)
return loadingScreen

def startupScreen(self):
print("startup screen ran")

self.hunterView = toga.WebView(style = Pack(
width=150, height=150, justify_content="center"))
print("WebView created")

if not hasattr(self.app, "local_port"):
self.app.start_local_server()

time.sleep(0.2)
hunterOpen = self.app.paths.app / "resources"  / "hunterButton.html"

self.hunterView.url = f"http://127.0.0.1:{self.app.local_port}/hunterButton.html"

asyncio.create_task(self.hunterMessageHandler(webview))

#server input field
self.serverLabel = toga.Label("Server IP: ", style = Pack(
padding = (0, 5),
color = "#9B9B9B"
))

self.serverInput = toga.TextInput(style=Pack(
flex=1,
color="#9B9B9B",
background_color="#282828",
))

self.serverBox = toga.Box(style=Pack(
direction=ROW,
padding=5,
color="#9B9B9B",
background_color="#282828"
))
self.serverBox.add(self.serverLabel)
self.serverBox.add(self.serverInput)

# ID input field
self.idLabel = toga.Label("Player ID: ", style=Pack(
padding=(0, 5),
color="#9B9B9B"
))
self.idInput = toga.TextInput(style=Pack(
flex=1,
color="#9B9B9B",
background_color="#282828",
))
self.idBox = toga.Box(style=Pack(
direction=ROW,
padding=5,
color="#9B9B9B",
background_color="#282828"
))
self.idBox.add(self.idLabel)
self.idBox.add(self.idInput)

#Game length input field
self.timeLabel = toga.Label("Game time ends:  ", style=Pack(
padding=(0, 5),
color="#9B9B9B",
background_color="#282828",
))

self.timeInput = toga.TextInput(style=Pack(
flex=1,
color="#9B9B9B",
background_color="#282828",
))

self.timeBox = toga.Box(style=Pack(
direction=ROW,
padding=5,
background_color="#282828"
))

self.timeBox.add(self.timeLabel)
self.timeBox.add(self.timeInput)

self.imageBox = toga.Box(style=Pack(
direction=ROW,
padding=5,
background_color="#282828",
flex=1,
visibility="visible"
))

self.imageBox.add(self.hunterLabel)
self.imageBox.add(self.hiderLabel)

self.idImageHide = toga.Button(icon=self.hider, style=Pack(width=150, height=150))
self.buttonbox = toga.Box(style=Pack(
direction=ROW,
padding=5,
background_color="#282828",
),
)
self.buttonbox.add(self.hunterView)
self.buttonbox.add(self.idImageHide)

self.typeSelectBox = toga.Box(style=Pack(
direction=COLUMN,
padding=5,
background_color="#282828",
justify_content="center"),
children=[self.buttonbox, self.imageBox]
)

# submit button
self.submitButton = toga.Button("Submit",
on_press = self.app.submitButton,
style = Pack(
padding = 5,
background_color = "#282828",
color = "#9B9B9B"
))

self.versionLabel = toga.Label("Version 4", style = Pack(
padding = 10,
background_color = "#141414",
color = "#9B9B9B",
text_align = "center",
))

self.versionBox = toga.Box(style = Pack(
direction = COLUMN,
background_color = "#141414",
height=50,
justify_content="end"
))
self.versionBox.add(self.versionLabel)

self.startUpScreen = toga.Box(style = Pack(
direction = COLUMN,
background_color = "#141414"
))

self.startUpScreen.add(self.serverBox)
self.startUpScreen.add(self.idBox)
self.startUpScreen.add(self.timeBox)
self.startUpScreen.add(self.typeSelectBox)
self.startUpScreen.add(self.submitButton)
self.startUpScreen.add(self.versionBox)
return self.startUpScreen

def waitingRoomScreen(self):
self.waitingRoomLabel = toga.Label("Waiting for game start", style = Pack(
padding = 10,
background_color = "#282828",
color = "#9B9B9B",
text_align = "center"
))

self.waitingRoomScreen = toga.Box(style = Pack(
direction = COLUMN,
background_color = "#141414"
))

self.versionLabel = toga.Label("Version 4", style = Pack(
padding = 10,
background_color = "#141414",
color = "#9B9B9B",
text_align = "center",
))

self.versionBox = toga.Box(style = Pack(
direction = COLUMN,
background_color = "#141414",
height=50,
justify_content="end"
))
self.versionBox.add(self.versionLabel)
self.waitingRoomScreen.add(self.waitingRoomLabel)
self.waitingRoomScreen.add(self.versionBox)
return self.waitingRoomScreen

def hiderScreen(self):
self.timerLabel = toga.Label("00:00",  style = Pack(
padding = 10,
background_color = "#282828",
color = "#9B9B9B",
text_align = "center",
height=175,
font_size=76,
horizontal_align_content="center"
))

self.killButton = toga.Button("Caught?",
on_press = self.app.dieButtomn,
style = Pack(
padding = 5,
background_color = "#282828",
color = "#9B9B9B"
))

self.hiderLabel = toga.Label("HIDER", style = Pack(
padding = 10,
color = "#9B9B9B",
text_align = "center",
font_size=36,
flex=1
))

self.topBox = toga.Box(style = Pack(
direction = ROW,
background_color = "#141414",
height=150,
width=400,
justify_content="center"
))
self.topBox.add(self.hiderLabel)

self.versionLabel = toga.Label("Version 4", style = Pack(
padding = 10,
background_color = "#141414",
color = "#9B9B9B",
text_align = "center",
))

self.versionBox = toga.Box(style = Pack(
direction = COLUMN,
background_color = "#141414",
height=50,
justify_content="end"
))
self.versionBox.add(self.versionLabel)

self.fillerBoxillerBox = toga.Box(style = Pack(flex=1))

self.hiderScreenView = toga.Box(style = Pack(
direction = COLUMN,
background_color = "#141414"
))

self.hiderScreenView.add(self.topBox)
self.hiderScreenView.add(self.timerLabel)
self.hiderScreenView.add(self.killButton)
self.hiderScreenView.add(self.fillerBoxillerBox)
self.hiderScreenView.add(self.versionBox)
return self.hiderScreenView

def checkScreen(self):
self.aliveQuestion = toga.Label("Are you sure?", style = Pack(
flex = 1,
padding = 10,
background_color = "#282828",
color = "#9B9B9B",
text_align = "center"
))

self.deadButton = toga.Button("Yes",
on_press = self.app.hiderKilled,
style = Pack(
flex = 1,
padding = 5,
background_color = "#282828",
color = "#9B9B9B"
))

self.aliveButton = toga.Button("No",
on_press = self.app.hiderSafe,
style = Pack(
flex = 1,
padding = 5,
background_color = "#282828",
color = "#9B9B9B"
))

self.checkTextBox = toga.Box(style = Pack(
direction = ROW
))

self.checkTextBox.add(self.aliveQuestion)

self.checkButtonBox = toga.Box(style = Pack(
direction = ROW,
flex = 1,
justify_content = "center",
padding = 10,
))
self.checkButtonBox.add(self.deadButton)
self.checkButtonBox.add(self.aliveButton)

self.versionLabel = toga.Label("Version 4",  style = Pack(
padding = 10,
background_color = "#141414",
color = "#9B9B9B",
text_align = "center",
))

self.versionBox = toga.Box(style = Pack(
direction = COLUMN,
background_color = "#141414",
height=50,
justify_content="end"
))
self.versionBox.add(self.versionLabel)

self.checkScreenView = toga.Box(style = Pack(
direction = COLUMN,
background_color = "#141414"
))
self.checkScreenView.add(self.checkTextBox)
self.checkScreenView.add(self.checkButtonBox)
self.checkScreenView.add(self.versionBox)
return self.checkScreenView

def hunterScreen(self):
self.tempLabel = toga.Label("Hunter screen, temp", style = Pack(
padding = 10,
background_color = "grey",
color = "black",
text_align = "center"
))

self.timerLabel = toga.Label("XX:XX", style = Pack(
padding = 10,
background_color = "#282828",
color = "#9B9B9B",
text_align = "center"
))

self.hunterScreenView = toga.Box(style = Pack(
direction = COLUMN,
background_color = "#141414"
))

self.hunterScreenView.add(self.tempLabel)
return self.hunterScreenView

# --- FUNCTIONS ---

def main():
return jsApp()
html актуально:

Код: Выделить всё




Hunter Button


[img]hunter.png[/img]




const msg = "uu";

function huntFunction (Toga) {

console.log("clicked");
window.location = "toga://hunt"

}



все в классе jsApp можно игнорировать, если в этом нет необходимости. Любые советы о том, как я могу:
1.получить полноразмерные значки на кнопках
2.накладывать изображения поверх кнопок
3.сделать недоступную веб-страницу Android, чтобы она не появлялась/быстрее перезагрузить правильный URL-адрес.
Конечная цель кнопок — сохранить имя пользователя с именем охотника или скрывающегося перед ним и сохранять изображение выделенным до тех пор, пока не начнется игра (не здесь, поскольку не моя проблема) или была нажата другая кнопка (я подожду, пока одна кнопка не заработает полностью, прежде чем разбираться с этим.

Подробнее здесь: https://stackoverflow.com/questions/798 ... ble-images
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «Javascript»